diff --git a/Cargo.lock b/Cargo.lock index e8df4515d87..64ee2bf0d65 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,7 +23,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cipher", "cpufeatures", ] @@ -45,7 +45,7 @@ version = "0.8.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "getrandom", "once_cell", "version_check", @@ -67,12 +67,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd" -[[package]] -name = "allocator-api2" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" - [[package]] name = "android-tzdata" version = "0.1.1" @@ -96,9 +90,9 @@ checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299" [[package]] name = "anstream" -version = "0.6.15" +version = "0.6.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" +checksum = "23a1e53f0f5d86382dafe1cf314783b2044280f406e7e1506368220ad11b1338" dependencies = [ "anstyle", "anstyle-parse", @@ -111,36 +105,36 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" +checksum = "8365de52b16c035ff4fcafe0092ba9390540e3e352870ac09933bebcaa2c8c56" [[package]] name = "anstyle-parse" -version = "0.2.5" +version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" +checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.1" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" +checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" dependencies = [ - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.4" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" +checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" dependencies = [ "anstyle", - "windows-sys 0.52.0", + "windows-sys 0.59.0", ] [[package]] @@ -151,9 +145,9 @@ checksum = "70033777eb8b5124a81a1889416543dddef2de240019b674c81285a2635a7e1e" [[package]] name = "anyhow" -version = "1.0.90" +version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" +checksum = "c042108f3ed77fd83760a5fd79b53be043192bb3b9dba91d8c574c0ada7850c8" [[package]] name = "arbitrary" @@ -182,12 +176,6 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" -[[package]] -name = "ascii" -version = "0.9.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eab1c04a571841102f5345a8fc0f6bb3d31c315dec879b5c6e42e40ce7ffa34e" - [[package]] name = "askama" version = "0.12.1" @@ -211,7 +199,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -226,7 +214,7 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acb1161c6b64d1c3d83108213c2a2533a342ac225aabd0bda218278c2ddb00c0" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -259,17 +247,29 @@ dependencies = [ "wait-timeout", ] +[[package]] +name = "async-channel" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b47800b0be77592da0afd425cc03468052844aff33b84e33cc696f64e77b6a" +dependencies = [ + "concurrent-queue", + "event-listener-strategy", + "futures-core", + "pin-project-lite", +] + [[package]] name = "async-compression" -version = "0.4.16" +version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "103db485efc3e41214fe4fda9f3dbeae2eb9082f48fd236e6095627a9422066e" +checksum = "0cb8f1d480b0ea3783ab015936d2a55c87e219676f0c0b7dec61494043f21857" dependencies = [ "flate2", "futures-core", "memchr", "pin-project-lite", - "tokio 1.40.0", + "tokio", ] [[package]] @@ -280,24 +280,24 @@ checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] name = "async-tungstenite" -version = "0.25.1" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cca750b12e02c389c1694d35c16539f88b8bbaa5945934fdc1b41a776688589" +checksum = "90e661b6cb0a6eb34d02c520b052daa3aa9ac0cc02495c9d066bbce13ead132b" dependencies = [ "futures-io", "futures-util", - "log 0.4.22", + "log", "pin-project-lite", "rustls-native-certs", "rustls-pki-types", - "tokio 1.40.0", - "tokio-rustls 0.25.0", - "tungstenite", + "tokio", + "tokio-rustls 0.26.0", + "tungstenite 0.24.0", ] [[package]] @@ -322,7 +322,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cfg-if 1.0.0", + "cfg-if", "libc", "miniz_oxide", "object 0.36.5", @@ -370,14 +370,14 @@ dependencies = [ "cexpr", "clang-sys", "itertools 0.10.5", - "log 0.4.22", + "log", "prettyplease", "proc-macro2", "quote", "regex", "rustc-hash 1.1.0", "shlex", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -401,7 +401,7 @@ dependencies = [ "arrayref", "arrayvec 0.7.6", "cc", - "cfg-if 1.0.0", + "cfg-if", "constant_time_eq", ] @@ -445,12 +445,6 @@ dependencies = [ "glob", ] -[[package]] -name = "build_const" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ae4235e6dac0694637c763029ecea1a2ec9e4e06ec2729bd21ba4d9c863eb7" - [[package]] name = "bumpalo" version = "3.16.0" @@ -499,7 +493,7 @@ checksum = "523363cbe1df49b68215efdf500b103ac3b0fb4836aed6d15689a076eadb8fff" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -508,16 +502,6 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" -[[package]] -name = "bytes" -version = "0.4.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c" -dependencies = [ - "byteorder", - "iovec", -] - [[package]] name = "bytes" version = "1.8.0" @@ -603,21 +587,21 @@ checksum = "3fce8dd7fcfcbf3a0a87d8f515194b49d6135acab73e18bd380d1d93bb1a15eb" dependencies = [ "heck 0.4.1", "indexmap 2.6.0", - "log 0.4.22", + "log", "proc-macro2", "quote", "serde", "serde_json", - "syn 2.0.82", + "syn 2.0.85", "tempfile", "toml 0.8.19", ] [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "jobserver", "libc", @@ -630,15 +614,9 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "nom 7.1.3", + "nom", ] -[[package]] -name = "cfg-if" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" - [[package]] name = "cfg-if" version = "1.0.0" @@ -753,7 +731,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -772,15 +750,6 @@ dependencies = [ "roff", ] -[[package]] -name = "cloudabi" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "cmake" version = "0.1.51" @@ -792,9 +761,9 @@ dependencies = [ [[package]] name = "colorchoice" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" +checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" [[package]] name = "colored" @@ -804,7 +773,7 @@ checksum = "5a5f741c91823341bebf717d4c71bda820630ce065443b58bd1b7451af008355" dependencies = [ "is-terminal", "lazy_static", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -817,19 +786,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "combine" -version = "3.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3da6baa321ec19e1cc41d31bf599f00c783d0517095cdaf0332e3fe8d20680" -dependencies = [ - "ascii", - "byteorder", - "either", - "memchr", - "unreachable", -] - [[package]] name = "comfy-table" version = "7.1.1" @@ -864,15 +820,24 @@ dependencies = [ "getopts", "lazy_static", "libc", - "log 0.4.22", - "miow 0.3.7", + "log", + "miow", "regex", "rustfix", "serde", "serde_derive", "serde_json", "tester", - "winapi 0.3.9", + "winapi", +] + +[[package]] +name = "concurrent-queue" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +dependencies = [ + "crossbeam-utils", ] [[package]] @@ -894,7 +859,7 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "wasm-bindgen", ] @@ -939,7 +904,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad067b451c08956709f8762dba86e049c124ea52858e3ab8d076ba2892caa437" dependencies = [ "autocfg", - "cfg-if 1.0.0", + "cfg-if", "libc", "scopeguard", "windows-sys 0.59.0", @@ -994,10 +959,10 @@ dependencies = [ "cranelift-isle", "gimli 0.28.1", "hashbrown 0.14.5", - "log 0.4.22", + "log", "regalloc2", "rustc-hash 1.1.0", - "smallvec 1.13.2", + "smallvec", "target-lexicon 0.12.16", ] @@ -1042,8 +1007,8 @@ checksum = "8327afc6c1c05f4be62fefce5b439fa83521c65363a322e86ea32c85e7ceaf64" dependencies = [ "cranelift-codegen", "hashbrown 0.14.5", - "log 0.4.22", - "smallvec 1.13.2", + "log", + "smallvec", "target-lexicon 0.12.16", ] @@ -1053,15 +1018,6 @@ version = "0.110.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56b08621c00321efcfa3eee6a3179adc009e21ea8d24ca7adc3c326184bc3f48" -[[package]] -name = "crc" -version = "1.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d663548de7f5cca343f1e0a48d14dcfb0e9eb4e079ec58883b7251539fa10aeb" -dependencies = [ - "build_const", -] - [[package]] name = "crc" version = "3.2.1" @@ -1083,7 +1039,7 @@ version = "1.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -1132,18 +1088,7 @@ version = "0.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" dependencies = [ - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-deque" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c20ff29ded3204c5106278a81a38f4b482636ed4fa1e6cfbeef193291beb29ed" -dependencies = [ - "crossbeam-epoch 0.8.2", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] @@ -1152,23 +1097,8 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" dependencies = [ - "crossbeam-epoch 0.9.18", - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-epoch" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "058ed274caafc1f60c4997b5fc07bf7dc7cca454af7c6e81edffe5f33f70dace" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "lazy_static", - "maybe-uninit", - "memoffset 0.5.6", - "scopeguard", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] @@ -1177,18 +1107,7 @@ version = "0.9.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" dependencies = [ - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-queue" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "774ba60a54c213d409d5353bda12d49cd68d14e45036a285234c8d6f91f92570" -dependencies = [ - "cfg-if 0.1.10", - "crossbeam-utils 0.7.2", - "maybe-uninit", + "crossbeam-utils", ] [[package]] @@ -1197,18 +1116,7 @@ version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" dependencies = [ - "crossbeam-utils 0.8.20", -] - -[[package]] -name = "crossbeam-utils" -version = "0.7.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3c7c73a2d1e9fc0886a08b93e98eb643461230d5f1925e4036204d5f2e261a8" -dependencies = [ - "autocfg", - "cfg-if 0.1.10", - "lazy_static", + "crossbeam-utils", ] [[package]] @@ -1226,8 +1134,8 @@ dependencies = [ "bitflags 2.6.0", "crossterm_winapi", "libc", - "parking_lot 0.12.3", - "winapi 0.3.9", + "parking_lot", + "winapi", ] [[package]] @@ -1236,7 +1144,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1255,12 +1163,6 @@ dependencies = [ "typenum", ] -[[package]] -name = "ct-codecs" -version = "1.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "026ac6ceace6298d2c557ef5ed798894962296469ec7842288ea64674201a2d1" - [[package]] name = "ctor" version = "0.1.26" @@ -1300,7 +1202,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.10.0", - "syn 2.0.82", + "syn 2.0.85", "thiserror", ] @@ -1324,7 +1226,7 @@ dependencies = [ "cynic-codegen", "darling 0.20.10", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1372,7 +1274,7 @@ dependencies = [ "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1394,7 +1296,7 @@ checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ "darling_core 0.20.10", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1403,11 +1305,11 @@ version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.5", - "lock_api 0.4.12", + "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -1416,12 +1318,12 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "cfg-if 1.0.0", - "crossbeam-utils 0.8.20", + "cfg-if", + "crossbeam-utils", "hashbrown 0.14.5", - "lock_api 0.4.12", + "lock_api", "once_cell", - "parking_lot_core 0.9.10", + "parking_lot_core", ] [[package]] @@ -1464,7 +1366,7 @@ checksum = "67e77553c4162a157adbf834ebae5b415acbecbeafc7a74b0e886657506a7611" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1508,7 +1410,7 @@ dependencies = [ "proc-macro2", "quote", "rustc_version 0.4.1", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1562,7 +1464,7 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "dirs-sys-next", ] @@ -1574,7 +1476,7 @@ checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1585,7 +1487,7 @@ checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" dependencies = [ "libc", "redox_users", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -1596,7 +1498,7 @@ checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1672,14 +1574,14 @@ dependencies = [ [[package]] name = "educe" -version = "0.4.23" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0042ff8246a363dbe77d2ceedb073339e85a804b9a47636c6e016a9a32c05f" +checksum = "e4bd92664bf78c4d3dba9b7cdafce6fa15b13ed3ed16175218196942e99168a8" dependencies = [ "enum-ordinalize", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.85", ] [[package]] @@ -1716,15 +1618,22 @@ dependencies = [ [[package]] name = "enum-ordinalize" -version = "3.1.15" +version = "4.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bf1fa3f06bbff1ea5b1a9c7b14aa992a39657db60a2759457328d7e058f49ee" +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 = [ - "num-bigint", - "num-traits", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1745,7 +1654,7 @@ dependencies = [ "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -1774,22 +1683,31 @@ dependencies = [ ] [[package]] -name = "fallible-iterator" -version = "0.2.0" +name = "event-listener" +version = "5.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" +dependencies = [ + "concurrent-queue", + "parking", + "pin-project-lite", +] [[package]] -name = "fallible-iterator" -version = "0.3.0" +name = "event-listener-strategy" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" +checksum = "0f214dc438f977e6d4e3500aaa277f5ad94ca83fbbd9b1a15713ce2344ccc5a1" +dependencies = [ + "event-listener", + "pin-project-lite", +] [[package]] -name = "fallible-streaming-iterator" -version = "0.1.9" +name = "fallible-iterator" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" [[package]] name = "fastrand" @@ -1804,7 +1722,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" dependencies = [ "colored 1.9.4", - "log 0.4.22", + "log", ] [[package]] @@ -1823,7 +1741,7 @@ version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35c0522e981e68cbfa8c3f978441a5f34b30b96e146b33cd3359176b50fe8586" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", "libredox", "windows-sys 0.59.0", @@ -1900,40 +1818,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] -name = "fuchsia-zircon" -version = "0.3.3" +name = "fuser" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -dependencies = [ - "bitflags 1.3.2", - "fuchsia-zircon-sys", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" - -[[package]] -name = "fuse" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80e57070510966bfef93662a81cb8aa2b1c7db0964354fa9921434f04b9e8660" +checksum = "2e697f6f62c20b6fad1ba0f84ae909f25971cf16e735273524e3977c94604cf8" dependencies = [ "libc", - "log 0.3.9", + "log", + "memchr", + "page_size", "pkg-config", - "thread-scoped", - "time 0.1.45", + "smallvec", + "zerocopy", ] -[[package]] -name = "futures" -version = "0.1.31" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a471a38ef8ed83cd6e40aa59c1ffe17db6855c18e3604d9c4ed8c08ebc28678" - [[package]] name = "futures" version = "0.3.31" @@ -1982,6 +1880,19 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" +[[package]] +name = "futures-lite" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52527eb5074e35e9339c6b4e8d12600c7128b68fb25dcb9fa9dec18f7c25f3a5" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "parking", + "pin-project-lite", +] + [[package]] name = "futures-macro" version = "0.3.31" @@ -1990,7 +1901,7 @@ checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -2005,6 +1916,12 @@ version = "0.3.31" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" +[[package]] +name = "futures-timer" +version = "3.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f288b0a4f20f9a56b5d1da57e2227c661b7b16168e2f72365f57b63326e29b24" + [[package]] name = "futures-util" version = "0.3.31" @@ -2048,7 +1965,7 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", @@ -2063,7 +1980,7 @@ checksum = "b0e085ded9f1267c32176b40921b9754c474f7dd96f7e808d4a982e48aa1e854" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -2072,7 +1989,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" dependencies = [ - "fallible-iterator 0.3.0", + "fallible-iterator", "indexmap 2.6.0", "stable_deref_trait", ] @@ -2097,7 +2014,7 @@ checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" dependencies = [ "aho-corasick", "bstr 1.10.0", - "log 0.4.22", + "log", "regex-automata 0.4.8", "regex-syntax 0.8.5", ] @@ -2108,84 +2025,28 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b363a30c165f666402fe6a3024d3bec7ebc898f96a4a23bd1c99f8dbf3f4f47" dependencies = [ - "log 0.4.22", + "log", "plain", "scroll", ] -[[package]] -name = "graphql-introspection-query" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f2a4732cf5140bd6c082434494f785a19cfb566ab07d1382c3671f5812fed6d" -dependencies = [ - "serde", -] - -[[package]] -name = "graphql-parser" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2ebc8013b4426d5b81a4364c419a95ed0b404af2b82e2457de52d9348f0e474" -dependencies = [ - "combine", - "thiserror", -] - [[package]] name = "graphql-ws-client" -version = "0.8.2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db7802310624d21a55797a3bc442dbe405424e9b2c967f86fb415634976f9a97" +checksum = "7a1d67ba08667c527d817fefa59feb12e87c7045261bcaecab3bcfb02d4a0102" dependencies = [ - "async-trait", - "futures 0.3.31", - "graphql_client", - "log 0.4.22", + "async-channel", + "cynic", + "futures-lite", + "futures-sink", + "futures-timer", + "log", "pin-project", "serde", "serde_json", "thiserror", - "tungstenite", -] - -[[package]] -name = "graphql_client" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09cdf7b487d864c2939b23902291a5041bc4a84418268f25fda1c8d4e15ad8fa" -dependencies = [ - "graphql_query_derive", - "serde", - "serde_json", -] - -[[package]] -name = "graphql_client_codegen" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a40f793251171991c4eb75bd84bc640afa8b68ff6907bc89d3b712a22f700506" -dependencies = [ - "graphql-introspection-query", - "graphql-parser", - "heck 0.4.1", - "lazy_static", - "proc-macro2", - "quote", - "serde", - "serde_json", - "syn 1.0.109", -] - -[[package]] -name = "graphql_query_derive" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00bda454f3d313f909298f626115092d348bc231025699f557b27e248475f48c" -dependencies = [ - "graphql_client_codegen", - "proc-macro2", - "syn 1.0.109", + "tungstenite 0.24.0", ] [[package]] @@ -2220,7 +2081,7 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "crunchy", ] @@ -2230,7 +2091,7 @@ version = "3.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4498fc115fa7d34de968184e473529abb40eeb6be8bc5f7faba3d08c316cb3e3" dependencies = [ - "log 0.4.22", + "log", "pest", "pest_derive", "quick-error", @@ -2287,7 +2148,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" dependencies = [ "ahash 0.8.11", - "allocator-api2", ] [[package]] @@ -2296,15 +2156,6 @@ version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" -[[package]] -name = "hashlink" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" -dependencies = [ - "hashbrown 0.14.5", -] - [[package]] name = "heapless" version = "0.7.17" @@ -2381,7 +2232,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" dependencies = [ - "bytes 1.8.0", + "bytes", "fnv", "itoa", ] @@ -2392,7 +2243,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ - "bytes 1.8.0", + "bytes", "http", ] @@ -2402,7 +2253,7 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ - "bytes 1.8.0", + "bytes", "futures-util", "http", "http-body", @@ -2443,7 +2294,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" dependencies = [ - "bytes 1.8.0", + "bytes", "futures-channel", "futures-util", "http", @@ -2452,8 +2303,8 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "smallvec 1.13.2", - "tokio 1.40.0", + "smallvec", + "tokio", "want", ] @@ -2469,7 +2320,7 @@ dependencies = [ "hyper-util", "rustls 0.23.15", "rustls-pki-types", - "tokio 1.40.0", + "tokio", "tokio-rustls 0.26.0", "tower-service", "webpki-roots", @@ -2481,12 +2332,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70206fc6890eaca9fde8a0bf71caa2ddfc9fe045ac9e5c70df101a7dbde866e0" dependencies = [ - "bytes 1.8.0", + "bytes", "http-body-util", "hyper", "hyper-util", "native-tls", - "tokio 1.40.0", + "tokio", "tokio-native-tls", "tower-service", ] @@ -2501,9 +2352,9 @@ dependencies = [ "hyper", "hyper-util", "pin-project-lite", - "tokio 1.40.0", - "tokio-tungstenite", - "tungstenite", + "tokio", + "tokio-tungstenite 0.21.0", + "tungstenite 0.21.0", ] [[package]] @@ -2512,7 +2363,7 @@ version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" dependencies = [ - "bytes 1.8.0", + "bytes", "futures-channel", "futures-util", "http", @@ -2520,7 +2371,7 @@ dependencies = [ "hyper", "pin-project-lite", "socket2", - "tokio 1.40.0", + "tokio", "tower-service", "tracing", ] @@ -2587,9 +2438,9 @@ version = "0.4.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" dependencies = [ - "crossbeam-deque 0.8.5", + "crossbeam-deque", "globset", - "log 0.4.22", + "log", "memchr", "regex-automata 0.4.8", "same-file", @@ -2660,7 +2511,7 @@ checksum = "9dd28cfd4cfba665d47d31c08a6ba637eed16770abca2eccbbc3ca831fef1e44" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -2720,7 +2571,7 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", ] [[package]] @@ -2749,15 +2600,6 @@ dependencies = [ "ghost", ] -[[package]] -name = "iovec" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2b3ea6ff95e175473f8ffe6a7eb7c00d054240321b84c57051175fe3c1e075e" -dependencies = [ - "libc", -] - [[package]] name = "ipnet" version = "2.10.1" @@ -2823,16 +2665,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "kernel32-sys" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "lalrpop-util" version = "0.20.2" @@ -2854,19 +2686,6 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "884e2677b40cc8c339eaefcb701c32ef1fd2493d71118dc0ca4b6a736c93bd67" -[[package]] -name = "lexical-core" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" -dependencies = [ - "arrayvec 0.5.2", - "bitflags 1.3.2", - "cfg-if 1.0.0", - "ryu", - "static_assertions", -] - [[package]] name = "lexical-sort" version = "0.3.1" @@ -2878,9 +2697,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.160" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0b21006cd1874ae9e650973c565615676dc4a274c965bb0a73796dac838ce4f" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "libfuzzer-sys" @@ -2899,8 +2718,8 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ - "cfg-if 1.0.0", - "windows-targets 0.48.5", + "cfg-if", + "windows-targets 0.52.6", ] [[package]] @@ -2917,18 +2736,17 @@ checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" dependencies = [ "bitflags 2.6.0", "libc", - "redox_syscall 0.5.7", + "redox_syscall", ] [[package]] -name = "libsqlite3-sys" -version = "0.25.2" +name = "libyml" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29f835d03d717946d28b1d1ed632eb6f0e24a299388ee623d0c23118d3e8a7fa" +checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" dependencies = [ - "cc", - "pkg-config", - "vcpkg", + "anyhow", + "version_check", ] [[package]] @@ -2972,15 +2790,6 @@ dependencies = [ "semver 1.0.23", ] -[[package]] -name = "lock_api" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" -dependencies = [ - "scopeguard", -] - [[package]] name = "lock_api" version = "0.4.12" @@ -2997,15 +2806,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" -[[package]] -name = "log" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e19e8d5c34a3e0e2223db8e060f9e8264aeeb5c5fc64a4ee9965c062211c024b" -dependencies = [ - "log 0.4.22", -] - [[package]] name = "log" version = "0.4.22" @@ -3033,7 +2833,7 @@ dependencies = [ "proc-macro2", "quote", "regex-syntax 0.8.5", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3075,16 +2875,6 @@ dependencies = [ "twox-hash", ] -[[package]] -name = "lzma-rs" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aba8ecb0450dfabce4ad72085eed0a75dffe8f21f7ada05638564ea9db2d7fb1" -dependencies = [ - "byteorder", - "crc 1.8.1", -] - [[package]] name = "lzma-rs" version = "0.3.0" @@ -3092,7 +2882,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e" dependencies = [ "byteorder", - "crc 3.2.1", + "crc", ] [[package]] @@ -3113,7 +2903,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8836fae9d0d4be2c8b4efcdd79e828a2faa058a90d005abf42f91cac5493a08e" dependencies = [ "nix 0.28.0", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3131,7 +2921,7 @@ version = "5.0.0-rc.1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3155,12 +2945,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" -[[package]] -name = "maybe-uninit" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" - [[package]] name = "md5" version = "0.7.0" @@ -3191,15 +2975,6 @@ dependencies = [ "libc", ] -[[package]] -name = "memoffset" -version = "0.5.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "043175f069eda7b85febe4a74abbaeff828d9f8b448515d3151a14a3542811aa" -dependencies = [ - "autocfg", -] - [[package]] name = "memoffset" version = "0.7.1" @@ -3246,9 +3021,9 @@ dependencies = [ [[package]] name = "minicov" -version = "0.3.5" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c71e683cd655513b99affab7d317deb690528255a0d5f717f1024093c12b169" +checksum = "def6d99771d7c499c26ad4d40eb6645eafd3a1553b35fc26ea5a489a45e82d9a" dependencies = [ "cc", "walkdir", @@ -3260,18 +3035,6 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" -[[package]] -name = "minisign" -version = "0.7.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "04ca8307d42371a74bca6693cd4e73a55f355f62f7f0367c3a0858712f29f389" -dependencies = [ - "ct-codecs", - "getrandom", - "rpassword", - "scrypt", -] - [[package]] name = "miniz_oxide" version = "0.8.0" @@ -3281,25 +3044,6 @@ dependencies = [ "adler2", ] -[[package]] -name = "mio" -version = "0.6.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4afd66f5b91bf2a3bc13fad0e21caedac168ca4c707504e75585648ae80e4cc4" -dependencies = [ - "cfg-if 0.1.10", - "fuchsia-zircon", - "fuchsia-zircon-sys", - "iovec", - "kernel32-sys", - "libc", - "log 0.4.22", - "miow 0.2.2", - "net2", - "slab", - "winapi 0.2.8", -] - [[package]] name = "mio" version = "1.0.2" @@ -3308,41 +3052,18 @@ checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", - "log 0.4.22", + "log", "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] -[[package]] -name = "mio-uds" -version = "0.6.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "afcb699eb26d4332647cc848492bbc15eafb26f08d0304550d5aa1f612e066f0" -dependencies = [ - "iovec", - "libc", - "mio 0.6.23", -] - -[[package]] -name = "miow" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebd808424166322d4a38da87083bfddd3ac4c131334ed55856112eb06d46944d" -dependencies = [ - "kernel32-sys", - "net2", - "winapi 0.2.8", - "ws2_32-sys", -] - [[package]] name = "miow" version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" dependencies = [ - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3374,7 +3095,7 @@ checksum = "1bb5c1d8184f13f7d0ccbeeca0def2f9a181bce2624302793005f5ca8aa62e5e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3384,7 +3105,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" dependencies = [ "libc", - "log 0.4.22", + "log", "openssl", "openssl-probe", "openssl-sys", @@ -3394,17 +3115,6 @@ dependencies = [ "tempfile", ] -[[package]] -name = "net2" -version = "0.2.39" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13b648036a2339d06de780866fbdfda0dde886de7b3af2ddeba8b14f4ee34ac" -dependencies = [ - "cfg-if 0.1.10", - "libc", - "winapi 0.3.9", -] - [[package]] name = "nix" version = "0.26.4" @@ -3412,7 +3122,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", - "cfg-if 1.0.0", + "cfg-if", "libc", "memoffset 0.7.1", "pin-utils", @@ -3425,23 +3135,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" dependencies = [ "bitflags 2.6.0", - "cfg-if 1.0.0", + "cfg-if", "cfg_aliases", "libc", "memoffset 0.9.1", ] -[[package]] -name = "nom" -version = "5.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08959a387a676302eebf4ddbcbc611da04285579f76f88ee0506c63b1a61dd4b" -dependencies = [ - "lexical-core", - "memchr", - "version_check", -] - [[package]] name = "nom" version = "7.1.3" @@ -3474,17 +3173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" dependencies = [ "overload", - "winapi 0.3.9", -] - -[[package]] -name = "num-bigint" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" -dependencies = [ - "num-integer", - "num-traits", + "winapi", ] [[package]] @@ -3493,15 +3182,6 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" -[[package]] -name = "num-integer" -version = "0.1.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" -dependencies = [ - "num-traits", -] - [[package]] name = "num-traits" version = "0.2.19" @@ -3610,7 +3290,7 @@ checksum = "6c62dcb6174f9cb326eac248f07e955d5d559c272730b6c03e396b443b562788" dependencies = [ "bstr 1.10.0", "normpath", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -3620,7 +3300,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6174bc48f102d208783c2c84bf931bb75927a617866870de8a4ea85597f871f5" dependencies = [ "bitflags 2.6.0", - "cfg-if 1.0.0", + "cfg-if", "foreign-types", "libc", "once_cell", @@ -3636,7 +3316,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3679,7 +3359,7 @@ dependencies = [ "proc-macro2", "proc-macro2-diagnostics", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3689,39 +3369,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" [[package]] -name = "parking_lot" -version = "0.9.0" +name = "page_size" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" +checksum = "30d5b2194ed13191c1999ae0704b7839fb18384fa22e49b57eeaa97d79ce40da" dependencies = [ - "lock_api 0.3.4", - "parking_lot_core 0.6.3", - "rustc_version 0.2.3", + "libc", + "winapi", ] [[package]] -name = "parking_lot" -version = "0.12.3" +name = "parking" +version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" -dependencies = [ - "lock_api 0.4.12", - "parking_lot_core 0.9.10", -] +checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" [[package]] -name = "parking_lot_core" -version = "0.6.3" +name = "parking_lot" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66b810a62be75176a80873726630147a5ca780cd33921e0b5709033e66b0a" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" dependencies = [ - "cfg-if 0.1.10", - "cloudabi", - "libc", - "redox_syscall 0.1.57", - "rustc_version 0.2.3", - "smallvec 0.6.14", - "winapi 0.3.9", + "lock_api", + "parking_lot_core", ] [[package]] @@ -3730,10 +3400,10 @@ version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "libc", - "redox_syscall 0.5.7", - "smallvec 1.13.2", + "redox_syscall", + "smallvec", "windows-targets 0.52.6", ] @@ -3802,7 +3472,7 @@ dependencies = [ "pest_meta", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3828,29 +3498,29 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +checksum = "be57f64e946e500c8ee36ef6331845d40a93055567ec57e8fae13efd33759b95" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +checksum = "3c0f5fad0874fc7abcd4d750e76917eaebbecaa2c20bde22e1dbeeba8beb758c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] name = "pin-project-lite" -version = "0.2.14" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" +checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" [[package]] name = "pin-utils" @@ -3947,12 +3617,12 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.22" +version = "0.2.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" +checksum = "64d1ec885c64d0457d564db4ec299b2dae3f9c02808b8ad9c3a089c591b18033" dependencies = [ "proc-macro2", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -3989,11 +3659,33 @@ dependencies = [ "version_check", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.85", +] + [[package]] name = "proc-macro2" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +checksum = "f139b0662de085916d1fb67d2b4169d1addddda1919e696f3252b740b629986e" dependencies = [ "unicode-ident", ] @@ -4006,7 +3698,7 @@ checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", "version_check", "yansi", ] @@ -4048,7 +3740,7 @@ checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -4074,7 +3766,7 @@ version = "0.11.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8c7c5fdde3cdae7203427dc4f0a68fe0ed09833edc525a03456b153b79828684" dependencies = [ - "bytes 1.8.0", + "bytes", "pin-project-lite", "quinn-proto", "quinn-udp", @@ -4082,7 +3774,7 @@ dependencies = [ "rustls 0.23.15", "socket2", "thiserror", - "tokio 1.40.0", + "tokio", "tracing", ] @@ -4092,7 +3784,7 @@ version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fadfaed2cd7f389d0161bb73eeb07b7b78f8691047a6f3e73caaeae55310a4a6" dependencies = [ - "bytes 1.8.0", + "bytes", "rand", "ring", "rustc-hash 2.0.0", @@ -4180,16 +3872,10 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" dependencies = [ - "crossbeam-deque 0.8.5", - "crossbeam-utils 0.8.20", + "crossbeam-deque", + "crossbeam-utils", ] -[[package]] -name = "redox_syscall" -version = "0.1.57" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" - [[package]] name = "redox_syscall" version = "0.5.7" @@ -4227,7 +3913,7 @@ checksum = "bcc303e793d3734489387d205e9b186fac9c6cfacedd98cbb2e8a5943595f3e6" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -4237,17 +3923,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ "hashbrown 0.13.2", - "log 0.4.22", + "log", "rustc-hash 1.1.0", "slice-group-by", - "smallvec 1.13.2", + "smallvec", ] [[package]] name = "regex" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" dependencies = [ "aho-corasick", "memchr", @@ -4328,7 +4014,7 @@ checksum = "f713147fbe92361e52392c73b8c9e48c04c6625bce969ef54dc901e58e042a7b" dependencies = [ "async-compression", "base64", - "bytes 1.8.0", + "bytes", "futures-channel", "futures-core", "futures-util", @@ -4341,7 +4027,7 @@ dependencies = [ "hyper-util", "ipnet", "js-sys", - "log 0.4.22", + "log", "mime", "mime_guess", "native-tls", @@ -4356,7 +4042,7 @@ dependencies = [ "serde_json", "serde_urlencoded", "sync_wrapper", - "tokio 1.40.0", + "tokio", "tokio-native-tls", "tokio-rustls 0.26.0", "tokio-socks", @@ -4378,7 +4064,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" dependencies = [ "cc", - "cfg-if 1.0.0", + "cfg-if", "getrandom", "libc", "spin", @@ -4393,7 +4079,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "395027076c569819ea6035ee62e664f5e03d74e281744f55261dd1afd939212b" dependencies = [ "bytecheck 0.8.0", - "bytes 1.8.0", + "bytes", "hashbrown 0.14.5", "indexmap 2.6.0", "munge", @@ -4413,7 +4099,7 @@ checksum = "09cb82b74b4810f07e460852c32f522e979787691b0b7b7439fe473e49d49b2f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -4429,9 +4115,9 @@ dependencies = [ [[package]] name = "rmp-serde" -version = "0.15.5" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "723ecff9ad04f4ad92fe1c8ca6c20d2196d9286e9c60727c4cb5511629260e9d" +checksum = "52e599a477cf9840e92f2cde9a7189e67b42c57532749bf90aea6ec10facd4db" dependencies = [ "byteorder", "rmp", @@ -4444,41 +4130,6 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" -[[package]] -name = "rpassword" -version = "7.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" -dependencies = [ - "libc", - "rtoolbox", - "windows-sys 0.48.0", -] - -[[package]] -name = "rtoolbox" -version = "0.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" -dependencies = [ - "libc", - "windows-sys 0.48.0", -] - -[[package]] -name = "rusqlite" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" -dependencies = [ - "bitflags 1.3.2", - "fallible-iterator 0.2.0", - "fallible-streaming-iterator", - "hashlink", - "libsqlite3-sys", - "smallvec 1.13.2", -] - [[package]] name = "rustc-demangle" version = "0.1.24" @@ -4497,15 +4148,6 @@ version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - [[package]] name = "rustc_version" version = "0.3.3" @@ -4531,7 +4173,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2c50b74badcddeb8f7652fa8323ce440b95286f8e4b64ebfd871c609672704e" dependencies = [ "anyhow", - "log 0.4.22", + "log", "serde", "serde_json", ] @@ -4555,7 +4197,7 @@ version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" dependencies = [ - "log 0.4.22", + "log", "ring", "rustls-pki-types", "rustls-webpki", @@ -4569,7 +4211,7 @@ version = "0.23.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5fbb44d7acc4e873d613422379f69f237a1b141928c02f6bc6ccfddddc2d7993" dependencies = [ - "log 0.4.22", + "log", "once_cell", "ring", "rustls-pki-types", @@ -4580,9 +4222,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.3" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5bfb394eeed242e909609f56089eecfe5fda225042e8b171791b9c95f5931e5" +checksum = "fcaf18a4f2be7326cd874a5fa579fae794320a0f388d365dca7e480e55f83f8a" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -4660,7 +4302,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ed36cdb20de66d89a17ea04b8883fc7a386f2cf877aaedca5005583ce4876ff" dependencies = [ "crossbeam-channel", - "futures 0.3.31", + "futures", "futures-channel", "futures-executor", "num_cpus", @@ -4678,21 +4320,12 @@ dependencies = [ ] [[package]] -name = "ryu" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" - -[[package]] -name = "salsa20" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a22f5af31f73a954c10289c93e8a50cc23d971e80ee446f1f6f7137a088213" -dependencies = [ - "cipher", -] - -[[package]] +name = "ryu" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" + +[[package]] name = "same-file" version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -4732,15 +4365,9 @@ dependencies = [ "proc-macro2", "quote", "serde_derive_internals", - "syn 2.0.82", + "syn 2.0.85", ] -[[package]] -name = "scoped-tls" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "332ffa32bf586782a3efaeb58f127980944bbc8c4d6913a86107ac2a5ab24b28" - [[package]] name = "scoped-tls" version = "1.0.1" @@ -4770,18 +4397,7 @@ checksum = "7f81c2fde025af7e69b1d1420531c8a8811ca898919db177141a85313b1cb932" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", -] - -[[package]] -name = "scrypt" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0516a385866c09368f0b5bcd1caff3366aace790fcd46e2bb032697bb172fd1f" -dependencies = [ - "pbkdf2", - "salsa20", - "sha2", + "syn 2.0.85", ] [[package]] @@ -4813,22 +4429,13 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser 0.7.0", -] - [[package]] name = "semver" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f301af10236f6df4160f7c3f04eec6dbc70ace82d23326abad5edee88801c6b6" dependencies = [ - "semver-parser 0.10.2", + "semver-parser", ] [[package]] @@ -4840,12 +4447,6 @@ dependencies = [ "serde", ] -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "semver-parser" version = "0.10.2" @@ -4863,9 +4464,9 @@ checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4" [[package]] name = "serde" -version = "1.0.211" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" +checksum = "3ea7893ff5e2466df8d720bb615088341b295f849602c6956047f8f80f0e9bc1" dependencies = [ "serde_derive", ] @@ -4902,13 +4503,13 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.211" +version = "1.0.213" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" +checksum = "7e85ad2009c50b58e87caa8cd6dac16bdf511bbfb7af6c33df902396aa480fa5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -4919,7 +4520,7 @@ checksum = "18d26a20a969b9e3fdf2fc2d9f21eda6c40e2de84c9408bb5d3b05d499aae711" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -4966,16 +4567,18 @@ dependencies = [ ] [[package]] -name = "serde_yaml" -version = "0.9.34+deprecated" +name = "serde_yml" +version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a8b1a1a2ebf674015cc02edccce75287f1a0130d394307b36743c2f5d504b47" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" dependencies = [ "indexmap 2.6.0", "itoa", + "libyml", + "memchr", "ryu", "serde", - "unsafe-libyaml", + "version_check", ] [[package]] @@ -4985,10 +4588,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e56dd856803e253c8f298af3f4d7eb0ae5e23a737252cd90bb4f3b435033b2d" dependencies = [ "dashmap 5.5.3", - "futures 0.3.31", + "futures", "lazy_static", - "log 0.4.22", - "parking_lot 0.12.3", + "log", + "parking_lot", "serial_test_derive", ] @@ -5000,7 +4603,7 @@ checksum = "91d129178576168c589c9ec973feedf7d3126c01ac2bf08795109aa35b69fb8f" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -5009,7 +4612,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] @@ -5020,7 +4623,7 @@ version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "cpufeatures", "digest", ] @@ -5040,7 +4643,7 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6c99835bad52957e7aa241d3975ed17c1e5f8c92026377d117a606f36b84b16" dependencies = [ - "bytes 1.8.0", + "bytes", "memmap2 0.6.2", ] @@ -5104,15 +4707,6 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "826167069c09b99d56f31e9ae5c99049e932a98c9dc2dac47645b08dbbf76ba7" -[[package]] -name = "smallvec" -version = "0.6.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" -dependencies = [ - "maybe-uninit", -] - [[package]] name = "smallvec" version = "1.13.2" @@ -5152,7 +4746,7 @@ version = "0.9.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" dependencies = [ - "lock_api 0.4.12", + "lock_api", ] [[package]] @@ -5173,7 +4767,7 @@ version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c6a0d765f5807e98a091107bae0a56ea3799f66a5de47b2c84c94a39c09974e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "hashbrown 0.14.5", ] @@ -5205,7 +4799,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -5227,9 +4821,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.82" +version = "2.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +checksum = "5023162dfcd14ef8f32034d8bcd4cc5ddc61ef7a247c024a33e24e1f24d21b56" dependencies = [ "proc-macro2", "quote", @@ -5268,13 +4862,19 @@ version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +[[package]] +name = "target-triple" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42a4d50cdb458045afc8131fd91b64904da29548bcb63c7236e0844936c13078" + [[package]] name = "tempfile" version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0f2c9fc62d0beef6951ccffd757e241266a2c833136efbe35af6cd2567dca5b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "fastrand", "once_cell", "rustix", @@ -5289,7 +4889,7 @@ checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" dependencies = [ "dirs-next", "rustversion", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5352,7 +4952,7 @@ checksum = "5999e24eaa32083191ba4e425deb75cdf25efefabe5aaccb7446dd0d4122a3f5" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -5361,7 +4961,7 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "getopts", "libc", "num_cpus", @@ -5379,37 +4979,31 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +checksum = "5d11abd9594d9b38965ef50805c5e469ca9cc6f197f883f717e0269a3057b3d5" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.64" +version = "1.0.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +checksum = "ae71770322cbd277e69d762a16c444af02aa0575ac0d174f0b9562d3b37f8602" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] -[[package]] -name = "thread-scoped" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bcbb6aa301e5d3b0b5ef639c9a9c7e2f1c944f177b460c04dc24c69b1fa2bd99" - [[package]] name = "thread_local" version = "1.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b9ef9bad013ada3808854ceac7b46812a6465ba368859a37e2100283d2d719c" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", ] @@ -5421,7 +5015,7 @@ checksum = "1b797afad3f312d1c66a56d11d0316f916356d11bd158fbc6ca6389ff6bf805a" dependencies = [ "libc", "wasi 0.10.0+wasi-snapshot-preview1", - "winapi 0.3.9", + "winapi", ] [[package]] @@ -5487,7 +5081,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec03259a0567ad58eed30812bc3e5eda8030f154abc70317ab57b14f00699ca4" dependencies = [ "idna 0.2.3", - "log 0.4.22", + "log", "regex", "serde_json", "thiserror", @@ -5496,38 +5090,14 @@ dependencies = [ [[package]] name = "tokio" -version = "0.1.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a09c0b5bb588872ab2f09afa13ee6e9dac11e10a0ec9e8e3ba39a5a5d530af6" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "mio 0.6.23", - "num_cpus", - "tokio-codec", - "tokio-current-thread", - "tokio-executor", - "tokio-fs", - "tokio-io", - "tokio-reactor", - "tokio-sync", - "tokio-tcp", - "tokio-threadpool", - "tokio-timer", - "tokio-udp", - "tokio-uds", -] - -[[package]] -name = "tokio" -version = "1.40.0" +version = "1.41.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +checksum = "145f3413504347a2be84393cc8a7d2fb4d863b375909ea59f2158261aa258bbb" dependencies = [ "backtrace", - "bytes 1.8.0", + "bytes", "libc", - "mio 1.0.2", + "mio", "pin-project-lite", "signal-hook-registry", "socket2", @@ -5535,78 +5105,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "tokio-codec" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25b2998660ba0e70d18684de5d06b70b70a3a747469af9dea7618cc59e75976b" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "tokio-io", -] - -[[package]] -name = "tokio-core" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87b1395334443abca552f63d4f61d0486f12377c2ba8b368e523f89e828cffd4" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "log 0.4.22", - "mio 0.6.23", - "scoped-tls 0.1.2", - "tokio 0.1.22", - "tokio-executor", - "tokio-io", - "tokio-reactor", - "tokio-timer", -] - -[[package]] -name = "tokio-current-thread" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1de0e32a83f131e002238d7ccde18211c0a5397f60cbfffcb112868c2e0e20e" -dependencies = [ - "futures 0.1.31", - "tokio-executor", -] - -[[package]] -name = "tokio-executor" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb2d1b8f4548dbf5e1f7818512e9c406860678f29c300cdf0ebac72d1a3a1671" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", -] - -[[package]] -name = "tokio-fs" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "297a1206e0ca6302a0eed35b700d292b275256f596e2f3fea7729d5e629b6ff4" -dependencies = [ - "futures 0.1.31", - "tokio-io", - "tokio-threadpool", -] - -[[package]] -name = "tokio-io" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57fc868aae093479e3131e3d165c93b1c7474109d13c90ec0dda2a1bbfff0674" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log 0.4.22", -] - [[package]] name = "tokio-macros" version = "2.4.0" @@ -5615,7 +5113,7 @@ checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -5625,26 +5123,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" dependencies = [ "native-tls", - "tokio 1.40.0", -] - -[[package]] -name = "tokio-reactor" -version = "0.1.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09bc590ec4ba8ba87652da2068d150dcada2cfa2e07faae270a5e0409aa51351" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log 0.4.22", - "mio 0.6.23", - "num_cpus", - "parking_lot 0.9.0", - "slab", - "tokio-executor", - "tokio-io", - "tokio-sync", + "tokio", ] [[package]] @@ -5655,7 +5134,7 @@ checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" dependencies = [ "rustls 0.22.4", "rustls-pki-types", - "tokio 1.40.0", + "tokio", ] [[package]] @@ -5666,17 +5145,17 @@ checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ "rustls 0.23.15", "rustls-pki-types", - "tokio 1.40.0", + "tokio", ] [[package]] name = "tokio-serde" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "911a61637386b789af998ee23f50aa30d5fd7edcec8d6d3dedae5e5815205466" +checksum = "caf600e7036b17782571dd44fa0a5cea3c82f60db5137f774a325a76a0d6852b" dependencies = [ "bincode", - "bytes 1.8.0", + "bytes", "educe", "futures-core", "futures-sink", @@ -5696,7 +5175,7 @@ dependencies = [ "either", "futures-util", "thiserror", - "tokio 1.40.0", + "tokio", ] [[package]] @@ -5707,63 +5186,10 @@ checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" dependencies = [ "futures-core", "pin-project-lite", - "tokio 1.40.0", + "tokio", "tokio-util", ] -[[package]] -name = "tokio-sync" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edfe50152bc8164fcc456dab7891fa9bf8beaf01c5ee7e1dd43a397c3cf87dee" -dependencies = [ - "fnv", - "futures 0.1.31", -] - -[[package]] -name = "tokio-tcp" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98df18ed66e3b72e742f185882a9e201892407957e45fbff8da17ae7a7c51f72" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "mio 0.6.23", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-threadpool" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df720b6581784c118f0eb4310796b12b1d242a7eb95f716a8367855325c25f89" -dependencies = [ - "crossbeam-deque 0.7.4", - "crossbeam-queue 0.2.3", - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "lazy_static", - "log 0.4.22", - "num_cpus", - "slab", - "tokio-executor", -] - -[[package]] -name = "tokio-timer" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93044f2d313c95ff1cb7809ce9a7a05735b012288a888b62d4434fd58c94f296" -dependencies = [ - "crossbeam-utils 0.7.2", - "futures 0.1.31", - "slab", - "tokio-executor", -] - [[package]] name = "tokio-tungstenite" version = "0.21.0" @@ -5771,47 +5197,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c83b561d025642014097b66e6c1bb422783339e0909e4429cde4749d1990bc38" dependencies = [ "futures-util", - "log 0.4.22", + "log", "rustls 0.22.4", - "rustls-native-certs", "rustls-pki-types", - "tokio 1.40.0", + "tokio", "tokio-rustls 0.25.0", - "tungstenite", + "tungstenite 0.21.0", "webpki-roots", ] [[package]] -name = "tokio-udp" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2a0b10e610b39c38b031a2fcab08e4b82f16ece36504988dcbd81dbba650d82" -dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "log 0.4.22", - "mio 0.6.23", - "tokio-codec", - "tokio-io", - "tokio-reactor", -] - -[[package]] -name = "tokio-uds" -version = "0.2.7" +name = "tokio-tungstenite" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab57a4ac4111c8c9dbcf70779f6fc8bc35ae4b2454809febac840ad19bd7e4e0" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ - "bytes 0.4.12", - "futures 0.1.31", - "iovec", - "libc", - "log 0.4.22", - "mio 0.6.23", - "mio-uds", - "tokio-codec", - "tokio-io", - "tokio-reactor", + "futures-util", + "log", + "rustls 0.23.15", + "rustls-native-certs", + "rustls-pki-types", + "tokio", + "tokio-rustls 0.26.0", + "tungstenite 0.24.0", ] [[package]] @@ -5820,11 +5228,11 @@ version = "0.7.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" dependencies = [ - "bytes 1.8.0", + "bytes", "futures-core", "futures-sink", "pin-project-lite", - "tokio 1.40.0", + "tokio", ] [[package]] @@ -5892,7 +5300,7 @@ dependencies = [ "futures-util", "pin-project", "pin-project-lite", - "tokio 1.40.0", + "tokio", "tower-layer", "tower-service", "tracing", @@ -5905,7 +5313,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" dependencies = [ "bitflags 2.6.0", - "bytes 1.8.0", + "bytes", "futures-util", "http", "http-body", @@ -5935,7 +5343,7 @@ version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "log 0.4.22", + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -5949,7 +5357,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -5968,7 +5376,7 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "log 0.4.22", + "log", "once_cell", "tracing-core", ] @@ -5996,7 +5404,7 @@ dependencies = [ "serde", "serde_json", "sharded-slab", - "smallvec 1.13.2", + "smallvec", "thread_local", "tracing", "tracing-core", @@ -6022,7 +5430,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -6044,49 +5452,57 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "trybuild" -version = "1.0.100" +version = "1.0.101" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8923cde76a6329058a86f04d033f0945a2c6df8b94093512e4ab188b3e3a8950" +checksum = "8dcd332a5496c026f1e14b7f3d2b7bd98e509660c04239c58b0ba38a12daded4" dependencies = [ "glob", "serde", "serde_derive", "serde_json", + "target-triple", "termcolor", "toml 0.8.19", ] [[package]] -name = "tun-tap" -version = "0.1.4" +name = "tungstenite" +version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a477a4e9367c72ac875d23cd07ac99ffa932497d8428767fed0cfa27bbabe50" +checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" dependencies = [ - "cc", - "futures 0.1.31", - "libc", - "mio 0.6.23", - "tokio-core", + "byteorder", + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "rand", + "rustls 0.22.4", + "rustls-pki-types", + "sha1", + "thiserror", + "url", + "utf-8", ] [[package]] name = "tungstenite" -version = "0.21.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ef1a641ea34f399a848dea702823bbecfb4c486f911735368f1f137cb8257e1" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" dependencies = [ "byteorder", - "bytes 1.8.0", + "bytes", "data-encoding", "http", "httparse", - "log 0.4.22", + "log", "rand", - "rustls 0.22.4", + "rustls 0.23.15", "rustls-pki-types", "sha1", "thiserror", - "url", "utf-8", ] @@ -6096,7 +5512,7 @@ version = "1.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "static_assertions", ] @@ -6138,12 +5554,9 @@ checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" [[package]] name = "unicase" -version = "2.7.0" +version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" [[package]] name = "unicode-bidi" @@ -6238,7 +5651,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d5c400339a9d1d17be34257d0b407e91d64af335e5b4fa49f4bf28467fc8d635" dependencies = [ "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -6248,9 +5661,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a02e67ac9634b10da9e4aa63a29a7920b8f1395eafef1ea659b2dd76dda96906" dependencies = [ "anyhow", - "bytes 1.8.0", + "bytes", "camino", - "log 0.4.22", + "log", "once_cell", "paste", "static_assertions", @@ -6269,7 +5682,7 @@ dependencies = [ "proc-macro2", "quote", "serde", - "syn 2.0.82", + "syn 2.0.85", "toml 0.5.11", "uniffi_meta", ] @@ -6281,7 +5694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "583bab49f2bdf5681f9732f8b67a7e555ad920dbb5427be21450217bf1818189" dependencies = [ "anyhow", - "bytes 1.8.0", + "bytes", "siphasher", "uniffi_checksum_derive", ] @@ -6318,21 +5731,6 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b55eedc365f81a3c32aea49baf23fa965e3cd85bcc28fb8045708c7388d124ef" -[[package]] -name = "unreachable" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "382810877fe448991dfc7f0dd6e3ae5d58088fd0ea5e35189655f84e6814fa56" -dependencies = [ - "void", -] - -[[package]] -name = "unsafe-libyaml" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "673aac59facbab8a9007c7f6108d11f63b603f7cabff99fabf650fea5c32b861" - [[package]] name = "untrusted" version = "0.9.0" @@ -6347,7 +5745,7 @@ checksum = "b74fc6b57825be3373f7054754755f03ac3a8f5d70015ccad699ba2029956f4a" dependencies = [ "base64", "flate2", - "log 0.4.22", + "log", "once_cell", "rustls 0.23.15", "rustls-pki-types", @@ -6418,13 +5816,13 @@ version = "0.18.0" dependencies = [ "anyhow", "async-trait", - "bytes 1.8.0", + "bytes", "dashmap 6.1.0", "derivative", "dunce", "filetime", "fs_extra", - "futures 0.3.31", + "futures", "getrandom", "indexmap 1.9.3", "lazy_static", @@ -6437,7 +5835,7 @@ dependencies = [ "slab", "tempfile", "thiserror", - "tokio 1.40.0", + "tokio", "tracing", "tracing-test", "typetag", @@ -6450,10 +5848,10 @@ name = "virtual-mio" version = "0.5.0" dependencies = [ "async-trait", - "bytes 1.8.0", + "bytes", "derivative", - "futures 0.3.31", - "mio 1.0.2", + "futures", + "mio", "serde", "socket2", "thiserror", @@ -6469,14 +5867,14 @@ dependencies = [ "base64", "bincode", "bytecheck 0.6.12", - "bytes 1.8.0", + "bytes", "derivative", "futures-util", "hyper", "hyper-tungstenite", "hyper-util", "libc", - "mio 1.0.2", + "mio", "pin-project-lite", "rkyv", "serde", @@ -6484,21 +5882,15 @@ dependencies = [ "smoltcp", "socket2", "thiserror", - "tokio 1.40.0", + "tokio", "tokio-serde", - "tokio-tungstenite", + "tokio-tungstenite 0.21.0", "tokio-util", "tracing", "tracing-test", "virtual-mio", ] -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "wai-bindgen-gen-core" version = "0.2.3" @@ -6660,19 +6052,13 @@ dependencies = [ "wast", ] -[[package]] -name = "wasite" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" - [[package]] name = "wasm-bindgen" version = "0.2.95" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "once_cell", "wasm-bindgen-macro", ] @@ -6684,11 +6070,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" dependencies = [ "bumpalo", - "log 0.4.22", + "log", "once_cell", "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", "wasm-bindgen-shared", ] @@ -6698,7 +6084,7 @@ version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cc7ec4f8827a71586374db3e87abdb5a2bb3a15afed140221307c3ec06b1f63b" dependencies = [ - "cfg-if 1.0.0", + "cfg-if", "js-sys", "wasm-bindgen", "web-sys", @@ -6722,7 +6108,7 @@ checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6742,7 +6128,7 @@ dependencies = [ "console_error_panic_hook", "js-sys", "minicov", - "scoped-tls 1.0.1", + "scoped-tls", "wasm-bindgen", "wasm-bindgen-futures", "wasm-bindgen-test-macro", @@ -6756,7 +6142,7 @@ checksum = "c97b2ef2c8d627381e51c071c2ab328eac606d3f69dd82bcbca20a9e389d95f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -6827,9 +6213,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.4.1" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -6844,8 +6230,8 @@ version = "5.0.0-rc.1" dependencies = [ "anyhow", "bindgen", - "bytes 1.8.0", - "cfg-if 1.0.0", + "bytes", + "cfg-if", "cmake", "derivative", "hashbrown 0.11.2", @@ -6888,10 +6274,12 @@ name = "wasmer-api" version = "0.1.0" dependencies = [ "anyhow", + "async-tungstenite", "base64", "cynic", - "futures 0.3.31", + "futures", "getrandom", + "graphql-ws-client", "harsh", "merge-streams", "pin-project-lite", @@ -6900,7 +6288,8 @@ dependencies = [ "serde_json", "serde_path_to_error", "time 0.3.36", - "tokio 1.40.0", + "tokio", + "tokio-tungstenite 0.24.0", "tracing", "url", "uuid", @@ -6918,14 +6307,14 @@ dependencies = [ "clap", "cynic", "derive_more", - "futures 0.3.31", + "futures", "indicatif", - "log 0.4.22", + "log", "reqwest", "serde", "serde_json", "shared-buffer", - "tokio 1.40.0", + "tokio", "tracing", "tracing-subscriber", "url", @@ -6955,7 +6344,7 @@ name = "wasmer-c-api" version = "5.0.0-rc.1" dependencies = [ "cbindgen", - "cfg-if 1.0.0", + "cfg-if", "enumset", "field-offset", "inline-c", @@ -6963,7 +6352,7 @@ dependencies = [ "libc", "paste", "thiserror", - "tokio 1.40.0", + "tokio", "tracing", "tracing-subscriber", "typetag", @@ -7026,10 +6415,10 @@ dependencies = [ "anyhow", "assert_cmd 2.0.16", "async-trait", - "bytes 1.8.0", + "bytes", "bytesize", "cargo_metadata", - "cfg-if 1.0.0", + "cfg-if", "chrono", "clap", "clap_complete", @@ -7041,8 +6430,8 @@ dependencies = [ "dirs", "dotenvy", "flate2", - "fuse", - "futures 0.3.31", + "fuser", + "futures", "futures-util", "hex", "http", @@ -7056,14 +6445,15 @@ dependencies = [ "is-terminal", "lazy_static", "libc", - "log 0.4.22", + "log", + "lzma-rs", "mac_address", - "mio 1.0.2", + "mio", "normpath", "object 0.32.2", "once_cell", "opener", - "parking_lot 0.12.3", + "parking_lot", "pathdiff", "predicates 3.1.2", "pretty_assertions", @@ -7073,7 +6463,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "serde_yaml", + "serde_yml", "sha2", "shared-buffer", "tar", @@ -7083,12 +6473,11 @@ dependencies = [ "time 0.1.45", "time 0.3.36", "tldextract", - "tokio 1.40.0", - "tokio-tungstenite", + "tokio", + "tokio-tungstenite 0.21.0", "toml 0.5.11", "tracing", "tracing-subscriber", - "tun-tap", "unix_mode", "url", "uuid", @@ -7107,7 +6496,6 @@ dependencies = [ "wasmer-emscripten", "wasmer-object", "wasmer-package", - "wasmer-registry", "wasmer-types", "wasmer-vm", "wasmer-wasix", @@ -7121,8 +6509,8 @@ name = "wasmer-compiler" version = "5.0.0-rc.1" dependencies = [ "backtrace", - "bytes 1.8.0", - "cfg-if 1.0.0", + "bytes", + "cfg-if", "enum-iterator", "enumset", "hashbrown 0.11.2", @@ -7138,7 +6526,7 @@ dependencies = [ "serde", "serde_bytes", "shared-buffer", - "smallvec 1.13.2", + "smallvec", "thiserror", "wasmer-object", "wasmer-types", @@ -7154,13 +6542,13 @@ version = "5.0.0-rc.1" dependencies = [ "anyhow", "bytesize", - "cfg-if 1.0.0", + "cfg-if", "clap", "colored 2.1.0", "distance", "fern", "is-terminal", - "log 0.4.22", + "log", "target-lexicon 0.12.16", "unix_mode", "wasmer-compiler", @@ -7182,7 +6570,7 @@ dependencies = [ "lazy_static", "more-asserts", "rayon", - "smallvec 1.13.2", + "smallvec", "target-lexicon 0.12.16", "tracing", "wasmer-compiler", @@ -7204,7 +6592,7 @@ dependencies = [ "regex", "rustc_version 0.4.1", "semver 1.0.23", - "smallvec 1.13.2", + "smallvec", "target-lexicon 0.12.16", "wasmer-compiler", "wasmer-types", @@ -7224,7 +6612,7 @@ dependencies = [ "lazy_static", "more-asserts", "rayon", - "smallvec 1.13.2", + "smallvec", "target-lexicon 0.12.16", "wasmer-compiler", "wasmer-types", @@ -7245,7 +6633,7 @@ dependencies = [ "semver 1.0.23", "serde", "serde_json", - "serde_yaml", + "serde_yml", "tempfile", "thiserror", "toml 0.8.19", @@ -7257,7 +6645,7 @@ name = "wasmer-derive" version = "5.0.0-rc.1" dependencies = [ "compiletest_rs", - "proc-macro-error", + "proc-macro-error2", "proc-macro2", "quote", "syn 1.0.109", @@ -7272,7 +6660,7 @@ dependencies = [ "getrandom", "lazy_static", "libc", - "log 0.4.22", + "log", "time 0.3.36", "wasmer", "wasmer-types", @@ -7315,7 +6703,7 @@ dependencies = [ "derivative", "dirs", "flate2", - "futures 0.3.31", + "futures", "hex", "insta", "libc", @@ -7331,8 +6719,7 @@ dependencies = [ "tar", "target-lexicon 0.12.16", "tempfile", - "tokio 1.40.0", - "wasmer-registry", + "tokio", ] [[package]] @@ -7348,7 +6735,7 @@ dependencies = [ "base64", "bincode", "bytecheck 0.6.12", - "bytes 1.8.0", + "bytes", "derivative", "lz4_flex", "num_enum", @@ -7389,8 +6776,8 @@ name = "wasmer-package" version = "0.1.0" dependencies = [ "anyhow", - "bytes 1.8.0", - "cfg-if 1.0.0", + "bytes", + "cfg-if", "ciborium", "flate2", "hexdump", @@ -7412,61 +6799,12 @@ dependencies = [ "webc", ] -[[package]] -name = "wasmer-registry" -version = "5.21.0" -dependencies = [ - "anyhow", - "async-tungstenite", - "clap", - "console", - "dialoguer", - "dirs", - "filetime", - "flate2", - "futures 0.3.31", - "futures-util", - "graphql-ws-client", - "graphql_client", - "hex", - "indexmap 1.9.3", - "indicatif", - "lazy_static", - "log 0.4.22", - "lzma-rs 0.2.0", - "minisign", - "pretty_assertions", - "rand", - "regex", - "reqwest", - "rpassword", - "rusqlite", - "semver 1.0.23", - "serde", - "serde_json", - "tar", - "tempfile", - "thiserror", - "time 0.3.36", - "tldextract", - "tokio 1.40.0", - "tokio-tungstenite", - "toml 0.5.11", - "tracing", - "url", - "wasmer-config", - "wasmer-wasm-interface", - "wasmparser 0.216.0", - "webc", - "whoami", -] - [[package]] name = "wasmer-swift" version = "0.1.0" dependencies = [ "thiserror", - "tokio 1.40.0", + "tokio", "uniffi", "virtual-fs", "wasmer", @@ -7516,9 +6854,9 @@ version = "5.0.0-rc.1" dependencies = [ "backtrace", "cc", - "cfg-if 1.0.0", + "cfg-if", "corosensei", - "crossbeam-queue 0.3.11", + "crossbeam-queue", "dashmap 6.1.0", "derivative", "enum-iterator", @@ -7550,13 +6888,13 @@ dependencies = [ "bincode", "blake3", "bytecheck 0.6.12", - "bytes 1.8.0", - "cfg-if 1.0.0", + "bytes", + "cfg-if", "chrono", "cooked-waker", "dashmap 6.1.0", "derivative", - "futures 0.3.31", + "futures", "getrandom", "heapless", "hex", @@ -7584,14 +6922,14 @@ dependencies = [ "serde", "serde_derive", "serde_json", - "serde_yaml", + "serde_yml", "sha2", "shared-buffer", "tempfile", "terminal_size", "termios", "thiserror", - "tokio 1.40.0", + "tokio", "tokio-stream", "toml 0.8.19", "tower", @@ -7633,7 +6971,7 @@ dependencies = [ "anyhow", "bitflags 1.3.2", "byteorder", - "cfg-if 1.0.0", + "cfg-if", "num_enum", "pretty_assertions", "serde", @@ -7649,28 +6987,16 @@ dependencies = [ "wasmer-types", ] -[[package]] -name = "wasmer-wasm-interface" -version = "5.0.0-rc.1" -dependencies = [ - "bincode", - "either", - "nom 5.1.3", - "serde", - "wasmparser 0.216.0", - "wat", -] - [[package]] name = "wasmer-wast" version = "5.0.0-rc.1" dependencies = [ "anyhow", - "futures 0.3.31", + "futures", "serde", "tempfile", "thiserror", - "tokio 1.40.0", + "tokio", "virtual-fs", "wasmer", "wasmer-types", @@ -7684,14 +7010,14 @@ version = "5.0.0-rc.1" dependencies = [ "anyhow", "build-deps", - "cfg-if 1.0.0", + "cfg-if", "clap", "clap_builder", "clap_derive", "clap_lex", "compiler-test-derive", "criterion", - "crossbeam-queue 0.3.11", + "crossbeam-queue", "glob", "lazy_static", "reqwest", @@ -7700,7 +7026,7 @@ dependencies = [ "tempfile", "test-generator", "test-log", - "tokio 1.40.0", + "tokio", "tracing", "tracing-subscriber", "ureq", @@ -7726,7 +7052,7 @@ checksum = "b07e84e3bcdab2f4301827623260ada2557596ca462f7470b60f5182a25270b1" dependencies = [ "arrayvec 0.7.6", "multi-stash", - "smallvec 1.13.2", + "smallvec", "spin", "wasmi_collections", "wasmi_core", @@ -7882,7 +7208,7 @@ checksum = "1cfc134be64da186b33675e0154827ba8eb4eb30579c1142cebec88607cd2cf6" dependencies = [ "http", "serde", - "tokio 1.40.0", + "tokio", "wasmparser 0.95.0", "wcgi", ] @@ -7905,8 +7231,8 @@ checksum = "56c452dd6074574080dea17d228caa5efc24f1e29650895c61333b0900734c20" dependencies = [ "anyhow", "base64", - "bytes 1.8.0", - "cfg-if 1.0.0", + "bytes", + "cfg-if", "ciborium", "document-features", "ignore", @@ -7940,7 +7266,7 @@ version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "998d2c24ec099a87daf9467808859f9d82b61f1d9c9701251aea037f514eae0e" dependencies = [ - "nom 7.1.3", + "nom", ] [[package]] @@ -7949,23 +7275,6 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" -[[package]] -name = "whoami" -version = "1.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" -dependencies = [ - "redox_syscall 0.5.7", - "wasite", - "web-sys", -] - -[[package]] -name = "winapi" -version = "0.2.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" - [[package]] name = "winapi" version = "0.3.9" @@ -7976,12 +7285,6 @@ dependencies = [ "winapi-x86_64-pc-windows-gnu", ] -[[package]] -name = "winapi-build" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" - [[package]] name = "winapi-i686-pc-windows-gnu" version = "0.4.0" @@ -8208,16 +7511,6 @@ dependencies = [ "memchr", ] -[[package]] -name = "ws2_32-sys" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59cefebd0c892fa2dd6de581e937301d8552cb44489cdff035c6187cb63fa5e" -dependencies = [ - "winapi 0.2.8", - "winapi-build", -] - [[package]] name = "xattr" version = "1.3.1" @@ -8277,7 +7570,7 @@ checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -8297,7 +7590,7 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.82", + "syn 2.0.85", ] [[package]] @@ -8311,13 +7604,13 @@ dependencies = [ "bzip2", "constant_time_eq", "crc32fast", - "crossbeam-utils 0.8.20", + "crossbeam-utils", "deflate64", "displaydoc", "flate2", "hmac", "indexmap 2.6.0", - "lzma-rs 0.3.0", + "lzma-rs", "memchr", "pbkdf2", "rand", @@ -8338,7 +7631,7 @@ dependencies = [ "bumpalo", "crc32fast", "lockfree-object-pool", - "log 0.4.22", + "log", "once_cell", "simd-adler32", ] diff --git a/Cargo.toml b/Cargo.toml index 3793f164f02..f298946d665 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,7 +14,7 @@ version.workspace = true [dependencies] wasmer = { version = "=5.0.0-rc.1", path = "lib/api", default-features = false } wasmer-compiler = { version = "=5.0.0-rc.1", path = "lib/compiler", features = [ - "compiler", + "compiler", ], optional = true } wasmer-compiler-cranelift = { version = "=5.0.0-rc.1", path = "lib/compiler-cranelift", optional = true } wasmer-compiler-singlepass = { version = "=5.0.0-rc.1", path = "lib/compiler-singlepass", optional = true } @@ -31,9 +31,9 @@ wasmer-middlewares = { version = "=5.0.0-rc.1", path = "lib/middlewares", option cfg-if = "1.0" tokio = { version = "1.39", features = [ - "rt", - "rt-multi-thread", - "macros", + "rt", + "rt-multi-thread", + "macros", ], optional = true } crossbeam-queue = "0.3.8" @@ -57,7 +57,6 @@ members = [ "lib/derive", "lib/emscripten", "lib/object", - "lib/registry", "lib/sys-utils", "lib/types", "lib/virtual-io", @@ -67,7 +66,6 @@ members = [ "lib/wai-bindgen-wasmer", "lib/wasi-types", "lib/wasix", - "lib/wasm-interface", "lib/journal", "lib/swift", "lib/package", @@ -78,9 +76,7 @@ members = [ "tests/wasi-wast", "tests/wasmer-argus", ] -exclude = [ - "./lib/cli/tests/packages/axum" -] +exclude = ["./lib/cli/tests/packages/axum"] resolver = "2" [workspace.package] @@ -116,16 +112,17 @@ rkyv = { version = "0.8.8", features = ["indexmap-2", "bytes-1"] } memmap2 = { version = "0.6.2" } toml = { version = "0.5.9", features = ["preserve_order"] } indexmap = "2" -serde_yaml = "0.9.34" +serde_yaml = { package = "serde_yml", version = "0.0.12" } libc = { version = "^0.2", default-features = false } gimli = { version = "0.28.1" } futures-util = { version = "0.3.31" } mio = "1" # MIO 1.0 starts at tokio version 1.39, hence the minimum requirement. -tokio = { version = "1.39.0", default-features = false} +tokio = { version = "1.39.0", default-features = false } socket2 = "0.5.7" pretty_assertions = "1.4.0" base64 = "0.22.0" +time = "0.3.36" [build-dependencies] test-generator = { path = "tests/lib/test-generator" } @@ -136,9 +133,9 @@ rustc_version = "0.4" [dev-dependencies] wasmer = { version = "=5.0.0-rc.1", path = "lib/api", features = [ - "compiler", - "singlepass", - "sys", + "compiler", + "singlepass", + "sys", ] } anyhow = "1.0" criterion = { version = "0.5", default-features = false } diff --git a/lib/backend-api/Cargo.toml b/lib/backend-api/Cargo.toml index 6c5888a746c..b2471e12683 100644 --- a/lib/backend-api/Cargo.toml +++ b/lib/backend-api/Cargo.toml @@ -19,13 +19,12 @@ wasmer-config = { version = "0.9.0", path = "../config" } wasmer-package.workspace = true webc.workspace = true - # crates.io dependencies. reqwest = { workspace = true, default-features = false, features = ["json"] } anyhow = "1" serde = { version = "1", features = ["derive"] } -time = { version = "0.3", features = ["formatting", "parsing"] } +time = { workspace = true, features = ["formatting", "parsing"] } tokio = { workspace = true } serde_json = "1" url = { version = "2", features = ["serde"] } @@ -37,6 +36,20 @@ serde_path_to_error = "0.1.14" harsh = "0.2.2" merge-streams = "0.1.2" + +# Subscriptions. +graphql-ws-client = { version = "0.11.0", features = [ + "tungstenite", + "client-cynic", +] } +tokio-tungstenite = { version = "0.24.0", features = [ + "rustls-tls-native-roots", +] } +async-tungstenite = { version = "0.28.0", features = [ + "tokio-runtime", + "tokio-rustls-native-certs", +] } + [target.'cfg(target_family = "wasm")'.dependencies.getrandom] version = "0.2.14" features = ["js"] diff --git a/lib/backend-api/src/lib.rs b/lib/backend-api/src/lib.rs index ff6c2d1faf0..9ded6a77ce6 100644 --- a/lib/backend-api/src/lib.rs +++ b/lib/backend-api/src/lib.rs @@ -7,6 +7,7 @@ mod error; pub mod global_id; pub mod query; pub mod stream; +pub mod subscription; pub mod types; use url::Url; diff --git a/lib/backend-api/src/query.rs b/lib/backend-api/src/query.rs index a08710cc6ea..f9cd5ebb190 100644 --- a/lib/backend-api/src/query.rs +++ b/lib/backend-api/src/query.rs @@ -57,6 +57,42 @@ pub async fn redeploy_app_by_id( .map(|v| v.redeploy_active_version.map(|v| v.app)) } +/// List all bindings associated with a particular package. +/// +/// If a version number isn't provided, this will default to the most recently +/// published version. +pub async fn list_bindings( + client: &WasmerClient, + name: &str, + version: Option<&str>, +) -> Result, anyhow::Error> { + client + .run_graphql_strict(types::GetBindingsQuery::build(GetBindingsQueryVariables { + name, + version, + })) + .await + .and_then(|b| { + b.package_version + .ok_or(anyhow::anyhow!("No bindings found!")) + }) + .map(|v| { + let mut bindings_packages = Vec::new(); + + for b in v.bindings.into_iter().flatten() { + let pkg = Bindings { + id: b.id.into_inner(), + url: b.url, + language: b.language, + generator: b.generator, + }; + bindings_packages.push(pkg); + } + + bindings_packages + }) +} + /// Revoke an existing token pub async fn revoke_token( client: &WasmerClient, diff --git a/lib/backend-api/src/subscription.rs b/lib/backend-api/src/subscription.rs new file mode 100644 index 00000000000..e16d59ef8c1 --- /dev/null +++ b/lib/backend-api/src/subscription.rs @@ -0,0 +1,64 @@ +use crate::{ + types::{PackageVersionReadySubscription, PackageVersionReadySubscriptionVariables}, + WasmerClient, +}; +use anyhow::Context; +use async_tungstenite::tungstenite::client::IntoClientRequest; +use cynic::SubscriptionBuilder; +use graphql_ws_client::Subscription; +use reqwest::header::HeaderValue; +use std::future::IntoFuture; + +pub async fn package_version_ready( + client: &WasmerClient, + package_version_id: &str, +) -> anyhow::Result< + Subscription< + cynic::StreamingOperation< + PackageVersionReadySubscription, + PackageVersionReadySubscriptionVariables, + >, + >, +> { + let mut url = client.graphql_endpoint().clone(); + if url.scheme() == "http" { + url.set_scheme("ws").unwrap(); + } else if url.scheme() == "https" { + url.set_scheme("wss").unwrap(); + } + + let url = url.to_string(); + let mut req = url.into_client_request()?; + + req.headers_mut().insert( + "Sec-WebSocket-Protocol", + HeaderValue::from_str("graphql-transport-ws").unwrap(), + ); + + if let Some(token) = client.auth_token() { + req.headers_mut().insert( + reqwest::header::AUTHORIZATION, + HeaderValue::from_str(&format!("Bearer {}", token))?, + ); + } + + req.headers_mut() + .insert(reqwest::header::USER_AGENT, client.user_agent.clone()); + + let (connection, _resp) = async_tungstenite::tokio::connect_async(req) + .await + .context("could not connect")?; + + let (client, actor) = graphql_ws_client::Client::build(connection).await?; + tokio::spawn(actor.into_future()); + + let stream = client + .subscribe(PackageVersionReadySubscription::build( + PackageVersionReadySubscriptionVariables { + package_version_id: cynic::Id::new(package_version_id), + }, + )) + .await?; + + Ok(stream) +} diff --git a/lib/backend-api/src/types.rs b/lib/backend-api/src/types.rs index 48e3a16dcb7..f8942b8ed96 100644 --- a/lib/backend-api/src/types.rs +++ b/lib/backend-api/src/types.rs @@ -2171,6 +2171,89 @@ mod queries { #[derive(cynic::Scalar, Debug, Clone)] pub struct BigInt(pub i64); + #[derive(cynic::Enum, Clone, Copy, Debug, PartialEq, Eq)] + pub enum ProgrammingLanguage { + Python, + Javascript, + } + + /// A library that exposes bindings to a Wasmer package. + #[derive(Debug, Clone)] + pub struct Bindings { + /// A unique ID specifying this set of bindings. + pub id: String, + /// The URL which can be used to download the files that were generated + /// (typically as a `*.tar.gz` file). + pub url: String, + /// The programming language these bindings are written in. + pub language: ProgrammingLanguage, + /// The generator used to generate these bindings. + pub generator: BindingsGenerator, + } + + #[derive(cynic::QueryVariables, Debug, Clone)] + pub struct GetBindingsQueryVariables<'a> { + pub name: &'a str, + pub version: Option<&'a str>, + } + + #[derive(cynic::QueryFragment, Debug, Clone)] + #[cynic(graphql_type = "Query", variables = "GetBindingsQueryVariables")] + pub struct GetBindingsQuery { + #[arguments(name: $name, version: $version)] + #[cynic(rename = "getPackageVersion")] + pub package_version: Option, + } + + #[derive(cynic::QueryFragment, Debug, Clone)] + #[cynic(graphql_type = "PackageVersion")] + pub struct PackageBindingsVersion { + pub bindings: Vec>, + } + + #[derive(cynic::QueryFragment, Debug, Clone)] + pub struct BindingsGenerator { + pub package_version: PackageVersion, + pub command_name: String, + } + + #[derive(cynic::QueryFragment, Debug, Clone)] + pub struct PackageVersionLanguageBinding { + pub id: cynic::Id, + pub language: ProgrammingLanguage, + pub url: String, + pub generator: BindingsGenerator, + pub __typename: String, + } + + #[derive(cynic::QueryVariables, Debug)] + pub struct PackageVersionReadySubscriptionVariables { + pub package_version_id: cynic::Id, + } + + #[derive(cynic::QueryFragment, Debug)] + #[cynic( + graphql_type = "Subscription", + variables = "PackageVersionReadySubscriptionVariables" + )] + pub struct PackageVersionReadySubscription { + #[arguments(packageVersionId: $package_version_id)] + pub package_version_ready: PackageVersionReadyResponse, + } + + #[derive(cynic::QueryFragment, Debug)] + pub struct PackageVersionReadyResponse { + pub state: PackageVersionState, + pub success: bool, + } + + #[derive(cynic::Enum, Clone, Copy, Debug)] + pub enum PackageVersionState { + WebcGenerated, + BindingsGenerated, + NativeExesGenerated, + } + #[derive(cynic::InlineFragments, Debug, Clone)] #[cynic(graphql_type = "Node", variables = "GetDeployAppVersionsByIdVars")] pub enum NodeDeployAppVersions { diff --git a/lib/cli/Cargo.toml b/lib/cli/Cargo.toml index b3fff81115a..7904366cb58 100644 --- a/lib/cli/Cargo.toml +++ b/lib/cli/Cargo.toml @@ -37,17 +37,17 @@ default = [ "static-artifact-create", ] -# Tun-tap client for connecting to Wasmer Edge VPNs -tun-tap = [ - "dep:tun-tap", - "virtual-net/tokio-tungstenite", - "tokio-tungstenite", - "mio", - "mac_address", - "dep:interfaces", -] +# # Tun-tap client for connecting to Wasmer Edge VPNs +# tun-tap = [ +# "dep:tun-tap", +# "virtual-net/tokio-tungstenite", +# "tokio-tungstenite", +# "mio", +# "mac_address", +# "dep:interfaces", +# ] journal = ["wasmer-wasix/journal"] -fuse = ["dep:fuse", "dep:time01", "dep:shared-buffer", "dep:rkyv"] +fuse = ["dep:fuser", "dep:time01", "dep:shared-buffer", "dep:rkyv"] backend = [] coredump = ["wasm-coredump-builder"] sys = ["compiler", "wasmer-vm"] @@ -99,6 +99,7 @@ disable-all-logging = [ ] headless = [] headless-minimal = ["headless", "disable-all-logging"] +telemetry = [] # Optional enable-serde = [ @@ -135,10 +136,6 @@ wasmer-wast = { version = "=5.0.0-rc.1", path = "../../tests/lib/wast", optional wasmer-types = { version = "=5.0.0-rc.1", path = "../types", features = [ "enable-serde", ] } -wasmer-registry = { version = "=5.21.0", path = "../registry", features = [ - "build-package", - "clap", -] } wasmer-object = { version = "=5.0.0-rc.1", path = "../object", optional = true } virtual-fs = { version = "0.18.0", path = "../virtual-fs", default-features = false, features = [ "host-fs", @@ -156,7 +153,7 @@ lazy_static = "1.4.0" shared-buffer = { workspace = true, optional = true } rkyv = { workspace = true, optional = true } -fuse = { version = "0.3", optional = true } +fuser = { version = "0.14.0", optional = true } time01 = { package = "time", version = "0.1.45", optional = true } @@ -215,7 +212,7 @@ humantime = "2.1.0" interfaces = { version = "0.0.9", optional = true } uuid = { version = "1.3.0", features = ["v4"] } -time = { version = "0.3.17", features = ["macros"] } +time = { workspace = true, features = ["macros"] } serde_yaml = { workspace = true } comfy-table = "7.0.1" @@ -228,13 +225,14 @@ tokio-tungstenite = { version = "0.21.0", features = [ "stream", ], optional = true } mac_address = { version = "1.1.5", optional = true } -tun-tap = { version = "0.1.4", features = ["tokio"], optional = true } +#tun-tap = { version = "0.1.4", features = ["tokio"], optional = true } clap_complete = "4.5.2" clap_mangen = "0.2.20" zip = { version = "2.1.3", default-features = false, features = ["deflate"] } console = "0.15.8" dotenvy = "0.15.7" +lzma-rs = "0.3.0" # NOTE: Must use different features for clap because the "color" feature does not # work on wasi due to the anstream dependency not compiling. @@ -268,7 +266,7 @@ reqwest = { workspace = true, default-features = false, features = [ [build-dependencies] -chrono = { version = "^0.4", default-features = false, features = [ +chrono = { version = "0.4.38", default-features = false, features = [ "std", "clock", ] } diff --git a/lib/cli/src/commands/add.rs b/lib/cli/src/commands/add.rs index 44cba7ae883..77b61858902 100644 --- a/lib/cli/src/commands/add.rs +++ b/lib/cli/src/commands/add.rs @@ -1,12 +1,17 @@ -use std::process::{Command, Stdio}; - +use super::AsyncCliCommand; +use crate::config::WasmerEnv; use anyhow::{Context, Error}; use clap::Parser; -use wasmer_registry::{wasmer_env::WasmerEnv, Bindings, ProgrammingLanguage}; +use std::process::{Command, Stdio}; +use wasmer_api::{ + types::{Bindings, ProgrammingLanguage}, + WasmerClient, +}; +use wasmer_config::package::NamedPackageIdent; /// Add a Wasmer package's bindings to your application. #[derive(Debug, Parser)] -pub struct Add { +pub struct CmdAdd { #[clap(flatten)] env: WasmerEnv, /// Add the JavaScript bindings using "npm install". @@ -25,20 +30,19 @@ pub struct Add { #[clap(long, groups = &["bindings", "py"])] pip: bool, /// The packages to add (e.g. "wasmer/wasmer-pack@0.5.0" or "python/python") - packages: Vec, + packages: Vec, } -impl Add { +#[async_trait::async_trait] +impl AsyncCliCommand for CmdAdd { + type Output = (); + /// Execute [`Add`]. - pub fn execute(&self) -> Result<(), Error> { + async fn run_async(self) -> Result { anyhow::ensure!(!self.packages.is_empty(), "No packages specified"); - let registry = self - .env - .registry_endpoint() - .context("Unable to determine which registry to use")?; - - let bindings = self.lookup_bindings(registry.as_str())?; + let client = self.env.client_unauthennticated()?; + let bindings = self.lookup_bindings(&client).await?; let mut cmd = self.target()?.command(&bindings)?; cmd.stdin(Stdio::null()) @@ -58,15 +62,18 @@ impl Add { Ok(()) } +} - fn lookup_bindings(&self, registry: &str) -> Result, Error> { +impl CmdAdd { + async fn lookup_bindings(&self, client: &WasmerClient) -> Result, Error> { println!("Querying Wasmer for package bindings"); let mut bindings_to_add = Vec::new(); let language = self.target()?.language(); for pkg in &self.packages { - let bindings = lookup_bindings_for_package(registry, pkg, &language) + let bindings = lookup_bindings_for_package(client, pkg, &language) + .await .with_context(|| format!("Unable to find bindings for {pkg}"))?; bindings_to_add.push(bindings); } @@ -90,18 +97,22 @@ impl Add { } } -fn lookup_bindings_for_package( - registry: &str, - pkg: &wasmer_registry::Package, +async fn lookup_bindings_for_package( + client: &WasmerClient, + pkg: &NamedPackageIdent, language: &ProgrammingLanguage, ) -> Result { - let all_bindings = - wasmer_registry::list_bindings(registry, &pkg.package(), pkg.version.as_deref())?; + let all_bindings = wasmer_api::query::list_bindings( + client, + &pkg.name, + pkg.version_opt().map(|v| v.to_string()).as_deref(), + ) + .await?; match all_bindings.iter().find(|b| b.language == *language) { Some(b) => { let Bindings { url, generator, .. } = b; - log::debug!("Found {pkg} bindings generated by {generator} at {url}"); + log::debug!("Found {pkg} bindings generated by {generator:?} at {url}"); Ok(b.clone()) } @@ -126,9 +137,9 @@ enum Target { impl Target { fn language(self) -> ProgrammingLanguage { match self { - Target::Pip => ProgrammingLanguage::PYTHON, + Target::Pip => ProgrammingLanguage::Python, Target::Pnpm { .. } | Target::Yarn { .. } | Target::Npm { .. } => { - ProgrammingLanguage::JAVASCRIPT + ProgrammingLanguage::Javascript } } } diff --git a/lib/cli/src/commands/cache.rs b/lib/cli/src/commands/cache.rs index bd6ff0f695a..c68cf606d61 100644 --- a/lib/cli/src/commands/cache.rs +++ b/lib/cli/src/commands/cache.rs @@ -1,8 +1,7 @@ -use std::{fs, path::Path}; - +use crate::config::WasmerEnv; use anyhow::Result; use clap::Parser; -use wasmer_registry::wasmer_env::WasmerEnv; +use std::{fs, path::Path}; #[derive(Debug, Parser)] /// The options for the `wasmer cache` subcommand @@ -21,7 +20,7 @@ impl Cache { match self.cmd { Cmd::Clean => { - clean(&cache_dir)?; + clean(cache_dir)?; } Cmd::Dir => { println!("{}", self.env.cache_dir().display()); diff --git a/lib/cli/src/commands/config.rs b/lib/cli/src/commands/config.rs index 261a189673d..0c8e0e05ebe 100644 --- a/lib/cli/src/commands/config.rs +++ b/lib/cli/src/commands/config.rs @@ -1,10 +1,12 @@ -use std::str::ParseBoolError; - +use crate::{ + config::{UpdateRegistry, WasmerConfig, WasmerEnv}, + VERSION, +}; use anyhow::{Context, Result}; use clap::Parser; -use wasmer_registry::{wasmer_env::WasmerEnv, WasmerConfig}; +use std::str::ParseBoolError; -use crate::VERSION; +use super::AsyncCliCommand; #[derive(Debug, Parser)] /// The options for the `wasmer config` subcommand: `wasmer config get --OPTION` or `wasmer config set [FLAG]` @@ -162,16 +164,22 @@ pub struct SetProxyUrl { pub url: String, } -impl Config { +#[async_trait::async_trait] +impl AsyncCliCommand for Config { + type Output = (); + /// Runs logic for the `config` subcommand - pub fn execute(&self) -> Result<()> { + async fn run_async(self) -> Result { self.inner_execute() + .await .context("failed to retrieve the wasmer config".to_string()) } +} - fn inner_execute(&self) -> Result<()> { +impl Config { + async fn inner_execute(&self) -> Result<()> { if let Some(s) = self.set.as_ref() { - return s.execute(&self.env); + return s.execute(&self.env).await; } let flags = &self.flags; @@ -228,7 +236,7 @@ impl Config { } impl GetOrSet { - fn execute(&self, env: &WasmerEnv) -> Result<()> { + async fn execute(&self, env: &WasmerEnv) -> Result<()> { let config_file = WasmerConfig::get_file_location(env.dir()); let mut config = env.config()?; @@ -262,22 +270,21 @@ impl GetOrSet { GetOrSet::Set(s) => { match s { StorableConfigField::RegistryUrl(s) => { - config.registry.set_current_registry(&s.url); + config.registry.set_current_registry(&s.url).await; let current_registry = config.registry.get_current_registry(); - if let Some(u) = wasmer_registry::utils::get_username(¤t_registry) - .ok() - .and_then(|o| o) - { - println!( + if let Ok(client) = env.client() { + if let Some(u) = wasmer_api::query::current_user(&client).await? { + println!( "Successfully logged into registry {current_registry:?} as user {u:?}" ); + } } } StorableConfigField::RegistryToken(t) => { config.registry.set_login_token_for_registry( &config.registry.get_current_registry(), &t.token, - wasmer_registry::config::UpdateRegistry::LeaveAsIs, + UpdateRegistry::LeaveAsIs, ); } StorableConfigField::TelemetryEnabled(t) => { diff --git a/lib/cli/src/commands/connect.rs b/lib/cli/src/commands/connect.rs index 3549087b060..419e052936a 100644 --- a/lib/cli/src/commands/connect.rs +++ b/lib/cli/src/commands/connect.rs @@ -36,65 +36,71 @@ pub struct CmdConnect { impl AsyncCliCommand for CmdConnect { type Output = (); - #[cfg(all(target_os = "linux", feature = "tun-tap"))] - async fn run_async(mut self) -> Result<(), anyhow::Error> { - use edge_schema::{AppId, NetworkIdEncodingMethod, WELL_KNOWN_VPN}; - use virtual_mio::Selector; + // Note (xdoardo, 28 Oct 2024): + // This part of the code is commented out as we did not manage + // to implement tun-tap yet. + // + // + // + //#[cfg(all(target_os = "linux", feature = "tun-tap"))] + //async fn run_async(mut self) -> Result<(), anyhow::Error> { + // use edge_schema::{AppId, NetworkIdEncodingMethod, WELL_KNOWN_VPN}; + // use virtual_mio::Selector; - use crate::net::TunTapSocket; + // use crate::net::TunTapSocket; - // If the URL does not include the well known postfix then add it - if !self.leave_postfix { - self.url.set_path(WELL_KNOWN_VPN); - } + // // If the URL does not include the well known postfix then add it + // if !self.leave_postfix { + // self.url.set_path(WELL_KNOWN_VPN); + // } - if self.print { - println!("websocket-url: {}", self.url.as_str()); - return Ok(()); - } + // if self.print { + // println!("websocket-url: {}", self.url.as_str()); + // return Ok(()); + // } - print!("Connecting..."); - let socket = TunTapSocket::create( - Selector::new(), - self.url.clone(), - self.leave_down == false, - self.ip, - ) - .await - .map_err(|err| { - println!("failed"); - err - })?; - println!("\rConnected to {} ", self.url.as_str()); + // print!("Connecting..."); + // let socket = TunTapSocket::create( + // Selector::new(), + // self.url.clone(), + // self.leave_down == false, + // self.ip, + // ) + // .await + // .map_err(|err| { + // println!("failed"); + // err + // })?; + // println!("\rConnected to {} ", self.url.as_str()); - for cidr in socket.ips().iter() { - println!("Your IP: {}/{}", cidr.ip, cidr.prefix); - } - for route in socket.routes().iter() { - println!( - "Gateway: {}/{} -> {}", - route.cidr.ip, route.cidr.prefix, route.via_router - ); - } - for cidr in socket.ips().iter() { - if let Some((app_id, _)) = - AppId::from_ip(&cidr.ip, NetworkIdEncodingMethod::PrivateProjection) - { - let ip = app_id.into_ip( - cidr.ip, - 0x00_1001, - NetworkIdEncodingMethod::PrivateProjection, - ); - println!("Instance: {}/{}", ip, cidr.prefix); - } - } - println!("Press ctrl-c to terminate"); - socket.await?; + // for cidr in socket.ips().iter() { + // println!("Your IP: {}/{}", cidr.ip, cidr.prefix); + // } + // for route in socket.routes().iter() { + // println!( + // "Gateway: {}/{} -> {}", + // route.cidr.ip, route.cidr.prefix, route.via_router + // ); + // } + // for cidr in socket.ips().iter() { + // if let Some((app_id, _)) = + // AppId::from_ip(&cidr.ip, NetworkIdEncodingMethod::PrivateProjection) + // { + // let ip = app_id.into_ip( + // cidr.ip, + // 0x00_1001, + // NetworkIdEncodingMethod::PrivateProjection, + // ); + // println!("Instance: {}/{}", ip, cidr.prefix); + // } + // } + // println!("Press ctrl-c to terminate"); + // socket.await?; - Ok(()) - } + // Ok(()) + //} - #[cfg(not(all(target_os = "linux", feature = "tun-tap")))] + //#[cfg(not(all(target_os = "linux", feature = "tun-tap")))] async fn run_async(self) -> Result<(), anyhow::Error> { Err(anyhow::anyhow!( "This CLI does not support the 'connect' command: only available on Linux (feature: tun-tap)" diff --git a/lib/cli/src/commands/create_exe.rs b/lib/cli/src/commands/create_exe.rs index f4151d21dc5..aef93caba46 100644 --- a/lib/cli/src/commands/create_exe.rs +++ b/lib/cli/src/commands/create_exe.rs @@ -1,15 +1,21 @@ //! Create a standalone native executable for a given Wasm file. +use self::utils::normalize_atom_name; +use super::CliCommand; +use crate::{ + common::{normalize_path, HashAlgorithm}, + config::WasmerEnv, + store::CompilerOptions, +}; +use anyhow::{anyhow, bail, Context, Result}; +use clap::Parser; +use serde::{Deserialize, Serialize}; use std::{ collections::BTreeMap, env, path::{Path, PathBuf}, process::{Command, Stdio}, }; - -use anyhow::{anyhow, bail, Context, Result}; -use clap::Parser; -use serde::{Deserialize, Serialize}; use tar::Archive; use wasmer::sys::Artifact; use wasmer::*; @@ -20,12 +26,6 @@ use webc::Container; use webc::PathSegments; use webc::{Metadata, Volume as WebcVolume}; -use self::utils::normalize_atom_name; -use crate::{ - common::{normalize_path, HashAlgorithm}, - store::CompilerOptions, -}; - const LINK_SYSTEM_LIBRARIES_WINDOWS: &[&str] = &["userenv", "Ws2_32", "advapi32", "bcrypt"]; const LINK_SYSTEM_LIBRARIES_UNIX: &[&str] = &["dl", "m", "pthread"]; @@ -33,6 +33,9 @@ const LINK_SYSTEM_LIBRARIES_UNIX: &[&str] = &["dl", "m", "pthread"]; #[derive(Debug, Parser)] /// The options for the `wasmer create-exe` subcommand pub struct CreateExe { + #[clap(flatten)] + env: WasmerEnv, + /// Input file #[clap(name = "FILE")] path: PathBuf, @@ -192,9 +195,11 @@ pub struct Volume { pub obj_file: PathBuf, } -impl CreateExe { +impl CliCommand for CreateExe { + type Output = (); + /// Runs logic for the `compile` subcommand - pub fn execute(&self) -> Result<()> { + fn run(self) -> Result { let path = normalize_path(&format!("{}", self.path.display())); let target_triple = self.target_triple.clone().unwrap_or_else(Triple::host); let mut cc = self.cross_compile.clone(); @@ -214,8 +219,13 @@ impl CreateExe { None => None, }; - let cross_compilation = - utils::get_cross_compile_setup(&mut cc, &target_triple, &starting_cd, url_or_version)?; + let cross_compilation = utils::get_cross_compile_setup( + &self.env, + &mut cc, + &target_triple, + &starting_cd, + url_or_version, + )?; if input_path.is_dir() { return Err(anyhow::anyhow!("input path cannot be a directory")); @@ -274,6 +284,7 @@ impl CreateExe { let mut entrypoint = get_entrypoint(&tempdir)?; create_header_files_in_dir(&tempdir, &mut entrypoint, &atoms, &self.precompiled_atom)?; link_exe_from_dir( + &self.env, &tempdir, output_path, &cross_compilation, @@ -844,6 +855,7 @@ fn compile_atoms( /// Compile the C code. fn run_c_compile( + env: &WasmerEnv, path_to_c_src: &Path, output_name: &Path, target: &Triple, @@ -864,7 +876,7 @@ fn run_c_compile( .arg("-c") .arg(path_to_c_src) .arg("-I") - .arg(utils::get_wasmer_include_directory()?); + .arg(utils::get_wasmer_include_directory(env)?); for i in include_dirs { command = command.arg("-I"); @@ -1111,7 +1123,9 @@ pub(crate) fn create_header_files_in_dir( } /// Given a directory, links all the objects from the directory appropriately +#[allow(clippy::too_many_arguments)] fn link_exe_from_dir( + env: &WasmerEnv, directory: &Path, output_path: PathBuf, cross_compilation: &CrossCompileSetup, @@ -1182,6 +1196,7 @@ fn link_exe_from_dir( && cross_compilation.target.operating_system == OperatingSystem::Windows { run_c_compile( + env, &directory.join("wasmer_main.c"), &directory.join("wasmer_main.o"), &cross_compilation.target, @@ -1580,6 +1595,8 @@ pub(super) mod utils { use target_lexicon::{Architecture, Environment, OperatingSystem, Triple}; use wasmer_types::{CpuFeature, Target}; + use crate::config::WasmerEnv; + use super::{CrossCompile, CrossCompileSetup, UrlOrVersion}; pub(in crate::commands) fn target_triple_to_target( @@ -1596,6 +1613,7 @@ pub(super) mod utils { } pub(in crate::commands) fn get_cross_compile_setup( + env: &WasmerEnv, cross_subc: &mut CrossCompile, target_triple: &Triple, starting_cd: &Path, @@ -1641,13 +1659,10 @@ pub(super) mod utils { } else { let wasmer_cache_dir = if *target_triple == Triple::host() && std::env::var("WASMER_DIR").is_ok() { - wasmer_registry::WasmerConfig::get_wasmer_dir() - .map_err(|e| anyhow!("{e}")) - .map(|o| o.join("cache")) + Some(env.cache_dir().to_path_buf()) } else { - get_libwasmer_cache_path() - } - .ok(); + get_libwasmer_cache_path(env).ok() + }; // check if the tarball for the target already exists locally let local_tarball = wasmer_cache_dir.as_ref().and_then(|wc| { @@ -1666,12 +1681,12 @@ pub(super) mod utils { }); if let Some(UrlOrVersion::Url(wasmer_release)) = specific_release.as_ref() { - let tarball = super::http_fetch::download_url(wasmer_release.as_ref())?; + let tarball = super::http_fetch::download_url(env, wasmer_release.as_ref())?; let (filename, tarball_dir) = find_filename(&tarball, target)?; Some(tarball_dir.join(filename)) } else if let Some(UrlOrVersion::Version(wasmer_release)) = specific_release.as_ref() { let release = super::http_fetch::get_release(Some(wasmer_release.clone()))?; - let tarball = super::http_fetch::download_release(release, target.clone())?; + let tarball = super::http_fetch::download_release(env, release, target.clone())?; let (filename, tarball_dir) = find_filename(&tarball, target)?; Some(tarball_dir.join(filename)) } else if let Some(local_tarball) = local_tarball.as_ref() { @@ -1679,7 +1694,7 @@ pub(super) mod utils { Some(tarball_dir.join(filename)) } else { let release = super::http_fetch::get_release(None)?; - let tarball = super::http_fetch::download_release(release, target.clone())?; + let tarball = super::http_fetch::download_release(env, release, target.clone())?; let (filename, tarball_dir) = find_filename(&tarball, target)?; Some(tarball_dir.join(filename)) } @@ -1841,12 +1856,8 @@ pub(super) mod utils { format!("{}-{}-{}", arch, os, env) } - pub(super) fn get_wasmer_dir() -> anyhow::Result { - wasmer_registry::WasmerConfig::get_wasmer_dir().map_err(|e| anyhow!("{e}")) - } - - pub(super) fn get_wasmer_include_directory() -> anyhow::Result { - let mut path = get_wasmer_dir()?; + pub(super) fn get_wasmer_include_directory(env: &WasmerEnv) -> anyhow::Result { + let mut path = env.dir().to_path_buf(); if path.clone().join("wasmer.h").exists() { return Ok(path); } @@ -1864,8 +1875,8 @@ pub(super) mod utils { } /// path to the static libwasmer - pub(super) fn get_libwasmer_path() -> anyhow::Result { - let path = get_wasmer_dir()?; + pub(super) fn get_libwasmer_path(env: &WasmerEnv) -> anyhow::Result { + let path = env.dir().to_path_buf(); // TODO: prefer headless Wasmer if/when it's a separate library. #[cfg(not(windows))] @@ -1881,8 +1892,8 @@ pub(super) mod utils { } /// path to library tarball cache dir - pub(super) fn get_libwasmer_cache_path() -> anyhow::Result { - let mut path = get_wasmer_dir()?; + pub(super) fn get_libwasmer_cache_path(env: &WasmerEnv) -> anyhow::Result { + let mut path = env.dir().to_path_buf(); path.push("cache"); std::fs::create_dir_all(&path)?; Ok(path) @@ -2174,11 +2185,12 @@ mod http_fetch { } pub(super) fn download_release( + env: &WasmerEnv, mut release: serde_json::Value, target_triple: wasmer::Triple, ) -> Result { // Test if file has been already downloaded - if let Ok(mut cache_path) = super::utils::get_libwasmer_cache_path() { + if let Ok(mut cache_path) = super::utils::get_libwasmer_cache_path(env) { let paths = std::fs::read_dir(&cache_path).and_then(|r| { r.map(|res| res.map(|e| e.path())) .collect::, std::io::Error>>() @@ -2231,10 +2243,11 @@ mod http_fetch { )); }; - download_url(&browser_download_url) + download_url(env, &browser_download_url) } pub(crate) fn download_url( + env: &WasmerEnv, browser_download_url: &str, ) -> Result { let filename = browser_download_url @@ -2268,7 +2281,7 @@ mod http_fetch { .copy_to(&mut file) .map_err(|e| anyhow::anyhow!("{e}"))?; - match super::utils::get_libwasmer_cache_path() { + match super::utils::get_libwasmer_cache_path(env) { Ok(mut cache_path) => { cache_path.push(&filename); if let Err(err) = std::fs::copy(&download_path, &cache_path) { @@ -2299,6 +2312,8 @@ mod http_fetch { use std::path::PathBuf; + use crate::{config::WasmerEnv, utils::unpack::try_unpack_targz}; + pub(crate) fn list_dir(target: &Path) -> Vec { use walkdir::WalkDir; WalkDir::new(target) @@ -2310,7 +2325,7 @@ mod http_fetch { pub(super) fn untar(tarball: &Path, target: &Path) -> Result> { let _ = std::fs::remove_dir(target); - wasmer_registry::try_unpack_targz(tarball, target, false)?; + try_unpack_targz(tarball, target, false)?; Ok(list_dir(target)) } } diff --git a/lib/cli/src/commands/gen_completions.rs b/lib/cli/src/commands/gen_completions.rs index 271c704a79c..e3b64794d7b 100644 --- a/lib/cli/src/commands/gen_completions.rs +++ b/lib/cli/src/commands/gen_completions.rs @@ -17,7 +17,7 @@ impl CmdGenCompletions { pub fn execute(&self) -> anyhow::Result<()> { let mut cmd = WasmerCmd::command(); - let name = cmd.get_name().to_string(); + let name = std::env::args().next().unwrap(); if let Some(out) = &self.out { let mut f = OpenOptions::new() .truncate(true) diff --git a/lib/cli/src/commands/init.rs b/lib/cli/src/commands/init.rs index 30e20ff2db0..7ef93e7a49b 100644 --- a/lib/cli/src/commands/init.rs +++ b/lib/cli/src/commands/init.rs @@ -1,13 +1,14 @@ +use crate::config::WasmerEnv; +use anyhow::Context; +use cargo_metadata::{CargoOpt, MetadataCommand}; +use clap::Parser; +use semver::VersionReq; use std::{ collections::HashMap, path::{Path, PathBuf}, }; -use anyhow::Context; -use cargo_metadata::{CargoOpt, MetadataCommand}; -use clap::Parser; -use semver::VersionReq; -use wasmer_registry::wasmer_env::WasmerEnv; +use super::AsyncCliCommand; static NOTE: &str = "# See more keys and definitions at https://docs.wasmer.io/registry/manifest"; @@ -94,9 +95,11 @@ struct MiniCargoTomlPackage { static WASMER_TOML_NAME: &str = "wasmer.toml"; -impl Init { - /// `wasmer init` execution - pub fn execute(&self) -> Result<(), anyhow::Error> { +#[async_trait::async_trait] +impl AsyncCliCommand for Init { + type Output = (); + + async fn run_async(self) -> Result<(), anyhow::Error> { let bin_or_lib = self.get_bin_or_lib()?; // See if the directory has a Cargo.toml file, if yes, copy the license / readme, etc. @@ -130,6 +133,7 @@ impl Init { } let constructed_manifest = construct_manifest( + &self.env, cargo_toml.as_ref(), &fallback_package_name, self.package_name.as_deref(), @@ -141,8 +145,8 @@ impl Init { self.template.as_ref(), self.include.as_slice(), self.quiet, - self.env.dir(), - )?; + ) + .await?; if let Some(parent) = target_file.parent() { let _ = std::fs::create_dir_all(parent); @@ -151,7 +155,9 @@ impl Init { // generate the wasmer.toml and exit Self::write_wasmer_toml(&target_file, &constructed_manifest) } +} +impl Init { /// Writes the metadata to a wasmer.toml file, making sure we include the /// [`NOTE`] so people get a link to the registry docs. fn write_wasmer_toml( @@ -355,7 +361,8 @@ impl GetBindingsResult { } #[allow(clippy::too_many_arguments)] -fn construct_manifest( +async fn construct_manifest( + env: &WasmerEnv, cargo_toml: Option<&MiniCargoTomlPackage>, fallback_package_name: &String, package_name: Option<&str>, @@ -367,7 +374,6 @@ fn construct_manifest( template: Option<&Template>, include_fs: &[String], quiet: bool, - wasmer_dir: &Path, ) -> Result { if let Some(ct) = cargo_toml.as_ref() { let msg = format!( @@ -386,11 +392,20 @@ fn construct_manifest( .map(|p| &p.name) .unwrap_or(fallback_package_name) }); - let namespace = namespace.or_else(|| { - wasmer_registry::whoami(wasmer_dir, None, None) - .ok() - .map(|o| o.1) - }); + let namespace = match namespace { + Some(n) => Some(n), + None => { + if let Ok(client) = env.client() { + if let Ok(Some(u)) = wasmer_api::query::current_user(&client).await { + Some(u.username) + } else { + None + } + } else { + None + } + } + }; let version = version.unwrap_or_else(|| { cargo_toml .as_ref() diff --git a/lib/cli/src/commands/journal/mount/cmd.rs b/lib/cli/src/commands/journal/mount/cmd.rs index 66d03f0e274..92dd4afb07e 100644 --- a/lib/cli/src/commands/journal/mount/cmd.rs +++ b/lib/cli/src/commands/journal/mount/cmd.rs @@ -36,7 +36,7 @@ impl CliCommand for CmdJournalMount { .build()?; // Mounts the journal file system at a path - fuse::mount(fs, &self.mount_path, &[])?; + fuser::mount(fs, &self.mount_path, &[])?; Ok(()) } } diff --git a/lib/cli/src/commands/journal/mount/fs.rs b/lib/cli/src/commands/journal/mount/fs.rs index 5544eed0f56..556797965a8 100644 --- a/lib/cli/src/commands/journal/mount/fs.rs +++ b/lib/cli/src/commands/journal/mount/fs.rs @@ -11,7 +11,7 @@ use std::{ time::Duration, }; -use fuse::{ +use fuser::{ FileAttr, Filesystem, ReplyAttr, ReplyBmap, ReplyCreate, ReplyData, ReplyDirectory, ReplyEmpty, ReplyEntry, ReplyLock, ReplyOpen, ReplyStatfs, ReplyWrite, ReplyXattr, Request, }; @@ -460,7 +460,7 @@ impl Filesystem for JournalFileSystem { mtime: time01::Timespec::new(file.last_modified() as i64, 0), ctime: time01::Timespec::new(file.created_time() as i64, 0), crtime: time01::Timespec::new(file.created_time() as i64, 0), - kind: fuse::FileType::RegularFile, + kind: fuser::FileType::RegularFile, perm: 0o644, nlink: 1, uid: 0, @@ -534,7 +534,7 @@ impl Filesystem for JournalFileSystem { mtime: time01::Timespec::new(file.last_modified() as i64, 0), ctime: time01::Timespec::new(file.created_time() as i64, 0), crtime: time01::Timespec::new(file.created_time() as i64, 0), - kind: fuse::FileType::RegularFile, + kind: fuser::FileType::RegularFile, perm: 0o644, nlink: 1, uid: 0, @@ -746,7 +746,7 @@ impl Filesystem for JournalFileSystem { mtime: now, ctime: now, crtime: now, - kind: fuse::FileType::RegularFile, + kind: fuser::FileType::RegularFile, perm: 0o644, nlink: 1, uid: 0, @@ -956,7 +956,7 @@ impl Filesystem for JournalFileSystem { // Compute the directory kind let kind = match entry.file_type() { Ok(ft) => file_type_to_kind(ft), - _ => fuse::FileType::RegularFile, + _ => fuser::FileType::RegularFile, }; // i + 1 means the index of the next entry @@ -1203,18 +1203,18 @@ impl Filesystem for JournalFileSystem { } } -fn file_type_to_kind(ft: virtual_fs::FileType) -> fuse::FileType { +fn file_type_to_kind(ft: virtual_fs::FileType) -> fuser::FileType { if ft.dir { - fuse::FileType::Directory + fuser::FileType::Directory } else if ft.symlink { - fuse::FileType::Symlink + fuser::FileType::Symlink } else if ft.block_device { - fuse::FileType::BlockDevice + fuser::FileType::BlockDevice } else if ft.char_device { - fuse::FileType::CharDevice + fuser::FileType::CharDevice } else if ft.socket { - fuse::FileType::Socket + fuser::FileType::Socket } else { - fuse::FileType::RegularFile + fuser::FileType::RegularFile } } diff --git a/lib/cli/src/commands/mod.rs b/lib/cli/src/commands/mod.rs index 8f5ae53e3c4..25fc275a6d4 100644 --- a/lib/cli/src/commands/mod.rs +++ b/lib/cli/src/commands/mod.rs @@ -178,12 +178,12 @@ impl WasmerCmd { #[cfg(feature = "compiler")] Some(Cmd::Compile(compile)) => compile.execute(), #[cfg(any(feature = "static-artifact-create", feature = "wasmer-artifact-create"))] - Some(Cmd::CreateExe(create_exe)) => create_exe.execute(), + Some(Cmd::CreateExe(create_exe)) => create_exe.run(), #[cfg(feature = "static-artifact-create")] Some(Cmd::CreateObj(create_obj)) => create_obj.execute(), - Some(Cmd::Config(config)) => config.execute(), + Some(Cmd::Config(config)) => config.run(), Some(Cmd::Inspect(inspect)) => inspect.execute(), - Some(Cmd::Init(init)) => init.execute(), + Some(Cmd::Init(init)) => init.run(), Some(Cmd::Login(login)) => login.run(), Some(Cmd::Auth(auth)) => auth.run(), Some(Cmd::Publish(publish)) => publish.run().map(|_| ()), @@ -205,7 +205,7 @@ impl WasmerCmd { #[cfg(target_os = "linux")] Some(Cmd::Binfmt(binfmt)) => binfmt.execute(), Some(Cmd::Whoami(whoami)) => whoami.run(), - Some(Cmd::Add(install)) => install.execute(), + Some(Cmd::Add(add)) => add.run(), // Deploy commands. Some(Cmd::Deploy(c)) => c.run(), @@ -402,7 +402,7 @@ enum Cmd { Whoami(Whoami), /// Add a Wasmer package's bindings to your application - Add(Add), + Add(CmdAdd), /// Run a WebAssembly file or Wasmer container #[clap(alias = "run-unstable")] diff --git a/lib/cli/src/commands/package/common/wait.rs b/lib/cli/src/commands/package/common/wait.rs index 8fcba61e201..67b54e3deea 100644 --- a/lib/cli/src/commands/package/common/wait.rs +++ b/lib/cli/src/commands/package/common/wait.rs @@ -1,5 +1,5 @@ -use futures_util::StreamExt; -use wasmer_api::WasmerClient; +use futures::StreamExt; +use wasmer_api::{types::PackageVersionState, WasmerClient}; /// Different conditions that can be "awaited" when publishing a package. #[derive(Debug, Clone, Copy, PartialEq, Eq, clap::ValueEnum)] @@ -86,16 +86,10 @@ pub async fn wait_package( return Ok(()); } - let registry_url = client.graphql_endpoint().to_string(); - let login_token = client.auth_token().unwrap_or_default().to_string(); let package_version_id = package_version_id.into_inner(); - let (mut stream, _) = wasmer_registry::subscriptions::subscribe_package_version_ready( - ®istry_url, - &login_token, - &package_version_id, - ) - .await?; + let mut stream = + wasmer_api::subscription::package_version_ready(client, &package_version_id).await?; let mut state: WaitPackageState = to_wait.into(); @@ -127,16 +121,9 @@ pub async fn wait_package( if let Some(data) = data.unwrap().data { match data.package_version_ready.state { - wasmer_registry::subscriptions::PackageVersionState::WEBC_GENERATED => { - state.container = false - } - wasmer_registry::subscriptions::PackageVersionState::BINDINGS_GENERATED => { - state.bindings = false - } - wasmer_registry::subscriptions::PackageVersionState::NATIVE_EXES_GENERATED => { - state.native_executables = false - } - wasmer_registry::subscriptions::PackageVersionState::Other(_) => {} + PackageVersionState::WebcGenerated => state.container = false, + PackageVersionState::BindingsGenerated => state.bindings = false, + PackageVersionState::NativeExesGenerated => state.native_executables = false, } } } diff --git a/lib/cli/src/commands/run/capabilities/mod.rs b/lib/cli/src/commands/run/capabilities/mod.rs index d6f95d08330..76cfd80dc4d 100644 --- a/lib/cli/src/commands/run/capabilities/mod.rs +++ b/lib/cli/src/commands/run/capabilities/mod.rs @@ -1,3 +1,5 @@ +use crate::config::WasmerEnv; + use super::PackageSource; use anyhow::anyhow; use sha2::{Digest, Sha256}; @@ -5,8 +7,8 @@ use std::{ path::{Path, PathBuf}, time::UNIX_EPOCH, }; + use wasmer_config::package::PackageSource as PackageSpecifier; -use wasmer_registry::wasmer_env::WasmerEnv; /// A custom implementation of the [`virtual_net::VirtualNetwork`] that asks users if they want to /// use networking features at runtime. diff --git a/lib/cli/src/commands/run/mod.rs b/lib/cli/src/commands/run/mod.rs index c4db7821297..94cc8d37ee3 100644 --- a/lib/cli/src/commands/run/mod.rs +++ b/lib/cli/src/commands/run/mod.rs @@ -33,8 +33,8 @@ use wasmer::{ use wasmer_compiler::ArtifactBuild; use wasmer_config::package::PackageSource as PackageSpecifier; use wasmer_package::utils::from_disk; -use wasmer_registry::{wasmer_env::WasmerEnv, Package}; use wasmer_types::ModuleHash; + #[cfg(feature = "journal")] use wasmer_wasix::journal::{LogFileJournal, SnapshotTrigger}; use wasmer_wasix::{ @@ -58,8 +58,8 @@ use webc::metadata::Manifest; use webc::Container; use crate::{ - commands::run::wasi::Wasi, common::HashAlgorithm, error::PrettyError, logging::Output, - store::StoreOptions, + commands::run::wasi::Wasi, common::HashAlgorithm, config::WasmerEnv, error::PrettyError, + logging::Output, store::StoreOptions, }; const TICK: Duration = Duration::from_millis(250); diff --git a/lib/cli/src/commands/run/wasi.rs b/lib/cli/src/commands/run/wasi.rs index f71fe8ac3d3..29bf885fefb 100644 --- a/lib/cli/src/commands/run/wasi.rs +++ b/lib/cli/src/commands/run/wasi.rs @@ -14,7 +14,6 @@ use url::Url; use virtual_fs::{DeviceFile, FileSystem, PassthruFileSystem, RootFileSystemBuilder}; use wasmer::{Engine, Function, Instance, Memory32, Memory64, Module, RuntimeError, Store, Value}; use wasmer_config::package::PackageSource as PackageSpecifier; -use wasmer_registry::wasmer_env::WasmerEnv; use wasmer_types::ModuleHash; #[cfg(feature = "journal")] use wasmer_wasix::journal::{LogFileJournal, SnapshotTrigger}; @@ -45,7 +44,10 @@ use wasmer_wasix::{ WasiVersion, }; -use crate::utils::{parse_envvar, parse_mapdir}; +use crate::{ + config::{UserRegistry, WasmerEnv}, + utils::{parse_envvar, parse_mapdir}, +}; use super::{ capabilities::{self, PkgCapabilityCache}, @@ -703,8 +705,7 @@ impl Wasi { } fn parse_registry(r: &str) -> Result { - let url = wasmer_registry::format_graphql(r).parse()?; - Ok(url) + UserRegistry::from(r).graphql_endpoint() } fn tokens_by_authority(env: &WasmerEnv) -> Result> { diff --git a/lib/cli/src/common.rs b/lib/cli/src/common.rs index 99fc28b4b6c..f65d4eaecac 100644 --- a/lib/cli/src/common.rs +++ b/lib/cli/src/common.rs @@ -37,7 +37,7 @@ pub struct WasmFeatures { } pub(crate) fn normalize_path(s: &str) -> String { - wasmer_registry::utils::normalize_path(s) + s.strip_prefix(r"\\?\").unwrap_or(s).to_string() } /// Hashing algorithm to be used for the module info diff --git a/lib/cli/src/config/mod.rs b/lib/cli/src/config/mod.rs index 23c95f21f3a..3dd54e40c59 100644 --- a/lib/cli/src/config/mod.rs +++ b/lib/cli/src/config/mod.rs @@ -26,7 +26,7 @@ lazy_static::lazy_static! { pub static ref DEFAULT_WASMER_CACHE_DIR: PathBuf = DEFAULT_WASMER_DIR.join("cache"); } -#[derive(Deserialize, Default, Serialize, Debug, PartialEq, Eq)] +#[derive(Deserialize, Serialize, Debug, PartialEq, Eq)] pub struct WasmerConfig { /// Whether or not telemetry is enabled. #[serde(default)] @@ -44,6 +44,17 @@ pub struct WasmerConfig { pub proxy: Proxy, } +impl Default for WasmerConfig { + fn default() -> Self { + Self { + telemetry_enabled: true, + update_notifications_enabled: true, + registry: Default::default(), + proxy: Default::default(), + } + } +} + #[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Default)] pub struct Proxy { pub url: Option, diff --git a/lib/cli/src/lib.rs b/lib/cli/src/lib.rs index 3769d75e11d..39883c527f0 100644 --- a/lib/cli/src/lib.rs +++ b/lib/cli/src/lib.rs @@ -15,8 +15,8 @@ #![allow(clippy::bool_comparison, clippy::match_like_matches_macro)] #![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] -#[cfg(all(target_os = "linux", feature = "tun-tap"))] -mod net; +//#[cfg(all(target_os = "linux", feature = "tun-tap"))] +//mod net; mod commands; mod common; @@ -26,7 +26,6 @@ mod error; mod c_gen; mod logging; mod opts; -mod package_source; mod store; mod types; mod utils; diff --git a/lib/cli/src/package_source.rs b/lib/cli/src/package_source.rs index 4c54b1ab7ee..e69de29bb2d 100644 --- a/lib/cli/src/package_source.rs +++ b/lib/cli/src/package_source.rs @@ -1,121 +0,0 @@ -//! Module for parsing and installing packages - -use std::str::FromStr; - -use url::Url; - -/// Source of a package -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum PackageSource { - /// Download from a URL - Url(Url), - /// Run a local file - File(String), - /// Download from a package - Package(wasmer_registry::Package), -} - -impl Default for PackageSource { - fn default() -> Self { - PackageSource::File(String::new()) - } -} - -impl FromStr for PackageSource { - type Err = String; - - fn from_str(s: &str) -> Result { - Self::parse(s) - } -} - -impl PackageSource { - /// Parses a package source and transforms it to a URL or a File - pub fn parse(s: &str) -> Result { - // If the file is a http:// URL, run the URL - if let Ok(url) = url::Url::parse(s) { - if url.scheme() == "http" || url.scheme() == "https" { - return Ok(Self::Url(url)); - } - } - - Ok(match wasmer_registry::Package::from_str(s) { - Ok(o) => Self::Package(o), - Err(_) => Self::File(s.to_string()), - }) - } -} - -#[test] -fn test_package_source() { - assert_eq!( - PackageSource::parse("registry.wasmer.io/graphql/python/python").unwrap(), - PackageSource::File("registry.wasmer.io/graphql/python/python".to_string()), - ); - - assert_eq!( - PackageSource::parse("/absolute/path/test.wasm").unwrap(), - PackageSource::File("/absolute/path/test.wasm".to_string()), - ); - - assert_eq!( - PackageSource::parse("C://absolute/path/test.wasm").unwrap(), - PackageSource::File("C://absolute/path/test.wasm".to_string()), - ); - - assert_eq!( - PackageSource::parse("namespace/name@latest").unwrap(), - PackageSource::Package(wasmer_registry::Package { - namespace: "namespace".to_string(), - name: "name".to_string(), - version: Some("latest".to_string()), - }) - ); - - assert_eq!( - PackageSource::parse("namespace/name@latest:command").unwrap(), - PackageSource::File("namespace/name@latest:command".to_string()), - ); - - assert_eq!( - PackageSource::parse("namespace/name@1.0.2").unwrap(), - PackageSource::Package(wasmer_registry::Package { - namespace: "namespace".to_string(), - name: "name".to_string(), - version: Some("1.0.2".to_string()), - }) - ); - - assert_eq!( - PackageSource::parse("namespace/name@1.0.2-rc.2").unwrap(), - PackageSource::Package(wasmer_registry::Package { - namespace: "namespace".to_string(), - name: "name".to_string(), - version: Some("1.0.2-rc.2".to_string()), - }) - ); - - assert_eq!( - PackageSource::parse("namespace/name").unwrap(), - PackageSource::Package(wasmer_registry::Package { - namespace: "namespace".to_string(), - name: "name".to_string(), - version: None, - }) - ); - - assert_eq!( - PackageSource::parse("https://wasmer.io/syrusakbary/python").unwrap(), - PackageSource::Url(url::Url::parse("https://wasmer.io/syrusakbary/python").unwrap()), - ); - - assert_eq!( - PackageSource::parse("command").unwrap(), - PackageSource::File("command".to_string()), - ); - - assert_eq!( - PackageSource::parse("python@latest").unwrap(), - PackageSource::File("python@latest".to_string()), - ); -} diff --git a/lib/cli/src/utils/mod.rs b/lib/cli/src/utils/mod.rs index 73fe8c4330f..c418b8e1796 100644 --- a/lib/cli/src/utils/mod.rs +++ b/lib/cli/src/utils/mod.rs @@ -4,6 +4,7 @@ pub(crate) mod package_wizard; pub(crate) mod prompts; pub(crate) mod render; pub(crate) mod timestamp; +pub(crate) mod unpack; use std::{ path::{Path, PathBuf}, diff --git a/lib/cli/src/utils/unpack.rs b/lib/cli/src/utils/unpack.rs new file mode 100644 index 00000000000..ddfb7f03c26 --- /dev/null +++ b/lib/cli/src/utils/unpack.rs @@ -0,0 +1,127 @@ +use crate::common::normalize_path; +use std::path::{Path, PathBuf}; + +/// Convenience function that will unpack .tar.gz files and .tar.bz +/// files to a target directory (does NOT remove the original .tar.gz) +pub fn try_unpack_targz>( + target_targz_path: P, + target_path: P, + strip_toplevel: bool, +) -> Result { + let target_targz_path = target_targz_path.as_ref().to_string_lossy().to_string(); + let target_targz_path = normalize_path(&target_targz_path); + let target_targz_path = Path::new(&target_targz_path); + + let target_path = target_path.as_ref().to_string_lossy().to_string(); + let target_path = normalize_path(&target_path); + let target_path = Path::new(&target_path); + + let open_file = || { + std::fs::File::open(target_targz_path) + .map_err(|e| anyhow::anyhow!("failed to open {}: {e}", target_targz_path.display())) + }; + + let try_decode_gz = || { + let file = open_file()?; + let gz_decoded = flate2::read::GzDecoder::new(&file); + let ar = tar::Archive::new(gz_decoded); + if strip_toplevel { + unpack_sans_parent(ar, target_path).map_err(|e| { + anyhow::anyhow!( + "failed to unpack (gz_ar_unpack_sans_parent) {}: {e}", + target_targz_path.display() + ) + }) + } else { + unpack_with_parent(ar, target_path).map_err(|e| { + anyhow::anyhow!( + "failed to unpack (gz_ar_unpack) {}: {e}", + target_targz_path.display() + ) + }) + } + }; + + let try_decode_xz = || { + let file = open_file()?; + let mut decomp: Vec = Vec::new(); + let mut bufread = std::io::BufReader::new(&file); + lzma_rs::xz_decompress(&mut bufread, &mut decomp).map_err(|e| { + anyhow::anyhow!( + "failed to unpack (try_decode_xz) {}: {e}", + target_targz_path.display() + ) + })?; + + let cursor = std::io::Cursor::new(decomp); + let mut ar = tar::Archive::new(cursor); + if strip_toplevel { + unpack_sans_parent(ar, target_path).map_err(|e| { + anyhow::anyhow!( + "failed to unpack (sans parent) {}: {e}", + target_targz_path.display() + ) + }) + } else { + ar.unpack(target_path).map_err(|e| { + anyhow::anyhow!( + "failed to unpack (with parent) {}: {e}", + target_targz_path.display() + ) + }) + } + }; + + try_decode_gz().or_else(|e1| { + try_decode_xz() + .map_err(|e2| anyhow::anyhow!("could not decode gz: {e1}, could not decode xz: {e2}")) + })?; + + Ok(Path::new(&target_targz_path).to_path_buf()) +} + +pub fn unpack_with_parent(mut archive: tar::Archive, dst: &Path) -> Result<(), anyhow::Error> +where + R: std::io::Read, +{ + use std::path::Component::Normal; + + let dst_normalized = normalize_path(dst.to_string_lossy().as_ref()); + + for entry in archive.entries()? { + let mut entry = entry?; + let path: PathBuf = entry + .path()? + .components() + .skip(1) // strip top-level directory + .filter(|c| matches!(c, Normal(_))) // prevent traversal attacks + .collect(); + if entry.header().entry_type().is_file() { + entry.unpack_in(&dst_normalized)?; + } else if entry.header().entry_type() == tar::EntryType::Directory { + std::fs::create_dir_all(Path::new(&dst_normalized).join(&path))?; + } + } + Ok(()) +} + +pub fn unpack_sans_parent(mut archive: tar::Archive, dst: &Path) -> std::io::Result<()> +where + R: std::io::Read, +{ + use std::path::Component::Normal; + + let dst_normalized = normalize_path(dst.to_string_lossy().as_ref()); + + for entry in archive.entries()? { + let mut entry = entry?; + let path: PathBuf = entry + .path()? + .components() + .skip(1) // strip top-level directory + .filter(|c| matches!(c, Normal(_))) // prevent traversal attacks + .collect(); + entry.unpack(Path::new(&dst_normalized).join(path))?; + } + Ok(()) +} diff --git a/lib/compiler-cranelift/Cargo.toml b/lib/compiler-cranelift/Cargo.toml index 19c04ee925a..31f14994c6c 100644 --- a/lib/compiler-cranelift/Cargo.toml +++ b/lib/compiler-cranelift/Cargo.toml @@ -56,6 +56,7 @@ std = [ "wasmer-types/std", ] core = ["hashbrown", "cranelift-codegen/core", "cranelift-frontend/core"] +enable-serde = [] [package.metadata.docs.rs] rustc-args = ["--cfg", "docsrs"] diff --git a/lib/compiler-singlepass/Cargo.toml b/lib/compiler-singlepass/Cargo.toml index 499e31747a7..ac7a541b47e 100644 --- a/lib/compiler-singlepass/Cargo.toml +++ b/lib/compiler-singlepass/Cargo.toml @@ -43,6 +43,7 @@ core = ["hashbrown", "wasmer-types/core"] unwind = ["gimli"] sse = [] avx = [] +enable-serde = [] [package.metadata.docs.rs] rustc-args = ["--cfg", "docsrs"] diff --git a/lib/derive/Cargo.toml b/lib/derive/Cargo.toml index 75769105112..57f873fa982 100644 --- a/lib/derive/Cargo.toml +++ b/lib/derive/Cargo.toml @@ -16,8 +16,10 @@ proc-macro = true syn = { version = "1.0.72", features = ["full", "extra-traits"] } quote = "1" proc-macro2 = "1" -proc-macro-error = "1.0.0" +proc-macro-error2 = "2.0.1" [dev-dependencies] -wasmer-types = { path = "../types", default-features=false, features = ["std"] } +wasmer-types = { path = "../types", default-features = false, features = [ + "std", +] } compiletest_rs = "0.6" diff --git a/lib/derive/src/lib.rs b/lib/derive/src/lib.rs index fe781efff80..6ec42cc237d 100644 --- a/lib/derive/src/lib.rs +++ b/lib/derive/src/lib.rs @@ -1,6 +1,6 @@ extern crate proc_macro; -use proc_macro_error::proc_macro_error; +use proc_macro_error2::proc_macro_error; use syn::{parse_macro_input, DeriveInput}; mod value_type; diff --git a/lib/derive/src/value_type.rs b/lib/derive/src/value_type.rs index 3ba535e5d38..3d3c2c76935 100644 --- a/lib/derive/src/value_type.rs +++ b/lib/derive/src/value_type.rs @@ -1,5 +1,5 @@ use proc_macro2::TokenStream; -use proc_macro_error::abort; +use proc_macro_error2::abort; use quote::quote; use syn::{Data, DeriveInput, Fields, Member, Meta, MetaList, NestedMeta}; diff --git a/lib/emscripten/Cargo.toml b/lib/emscripten/Cargo.toml index 57dcd953937..d743c32f4d8 100644 --- a/lib/emscripten/Cargo.toml +++ b/lib/emscripten/Cargo.toml @@ -17,7 +17,7 @@ byteorder = "1.3" lazy_static = "1.4" libc = { workspace = true, default-features = true } log = "0.4" -time = { version = "0.3", features = ["std", "formatting"] } +time = { workspace = true, features = ["std", "formatting"] } wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false } wasmer-types = { path = "../types", version = "=5.0.0-rc.1" } diff --git a/lib/registry/Cargo.toml b/lib/registry/Cargo.toml deleted file mode 100644 index 6c38ce52377..00000000000 --- a/lib/registry/Cargo.toml +++ /dev/null @@ -1,91 +0,0 @@ -[package] -name = "wasmer-registry" -version = "5.21.0" -description = "Crate to interact with the wasmer registry, download packages, etc." -authors.workspace = true -edition.workspace = true -homepage.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true - -[features] -build-package = [ - "rusqlite", - "indexmap", - "wasmer-wasm-interface", - "wasmparser", - "rpassword", - "minisign", - "time", -] -full = [] - -[dependencies] -anyhow = "1.0.65" -clap = { version = "4.4.0", default-features = false, features = [ - "derive", - "env", -], optional = true } -console = "0.15.2" -dialoguer = "0.11.0" -dirs = "4.0.0" -filetime = "0.2.19" -flate2 = "1.0.24" -futures = "0.3" -futures-util = { workspace = true } -graphql-ws-client = { version = "0.8.0", features = [ - "async-tungstenite", - "client-graphql-client", -] } -graphql_client = "0.13.0" -hex = "0.4.3" -indexmap = { version = "1.9.3", optional = true } -indicatif = "0.17.2" -lazy_static = "1.4.0" -log = "0.4.17" -lzma-rs = "0.2.0" -minisign = { version = "0.7.2", optional = true } -rand = "0.8.5" -regex = "1.7.0" -reqwest = { workspace = true, default-features = false, features = [ - "blocking", - "multipart", - "json", - "stream", -] } -rpassword = { version = "7.2.0", optional = true } -rusqlite = { version = "0.28.0", optional = true, features = ["bundled"] } -semver = "1.0.14" -serde = { version = "1.0.145", features = ["derive"] } -serde_json = "1.0.85" -tar = "0.4.38" -tempfile = "3.6.0" -thiserror = "1.0.37" -time = { version = "0.3.17", default-features = false, features = [ - "parsing", - "std", - "formatting", -], optional = true } -tldextract = "0.6.0" -tokio = { workspace = true, features = ["rt-multi-thread"] } -tokio-tungstenite = { version = "0.21", features = ["rustls-tls-native-roots"] } -toml.workspace = true -tracing = "0.1.40" -url = "2.5.0" -wasmer-config = { version = "0.9.0", path = "../config" } -wasmer-wasm-interface = { version = "5.0.0-rc.1", path = "../wasm-interface", optional = true } -wasmparser = { workspace = true, optional = true } -whoami = "1.2.3" -webc.workspace = true -async-tungstenite = { version = "0.25.1", features = [ - "tokio-runtime", - "tokio-rustls-native-certs", -] } - -[dev-dependencies] -pretty_assertions.workspace = true - -[package.metadata.docs.rs] -features = ["build-package"] -rustc-args = ["--cfg", "docsrs"] diff --git a/lib/registry/README.md b/lib/registry/README.md deleted file mode 100644 index 625820a77e4..00000000000 --- a/lib/registry/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# wasmer-registry - -This crate provides integration with the Wasmer package registry GraphQL API. - -## Development - -### Updating the GraphQL Schema - -The GraphQL API schema used for generating queries and mutations is located at -`./graphql/schema.graphql`. - -To update it to a deployed version of the backend, run: - -```bash -npx get-graphql-schema https://registry.wasmer.wtf/graphql > graphql/schema.graphql -``` - -### Formatting GraphQL Files - -To format the GraphQL query and mutation files, run: - -```bash -npx prettier --write ./graphql/**/*.graphql -``` diff --git a/lib/registry/graphql/mutations/generate_deploy_token.graphql b/lib/registry/graphql/mutations/generate_deploy_token.graphql deleted file mode 100644 index 4c4244b9997..00000000000 --- a/lib/registry/graphql/mutations/generate_deploy_token.graphql +++ /dev/null @@ -1,5 +0,0 @@ -mutation GenerateDeployToken($appVersionId: String!) { - generateDeployToken(input: { deployAppVersionId: $configId }) { - token - } -} diff --git a/lib/registry/graphql/mutations/new_nonce.graphql b/lib/registry/graphql/mutations/new_nonce.graphql deleted file mode 100644 index b5a6b1827e8..00000000000 --- a/lib/registry/graphql/mutations/new_nonce.graphql +++ /dev/null @@ -1,7 +0,0 @@ -mutation NewNonce($name: String!, $callbackUrl: String!) { - newNonce(input: { name: $name, callbackUrl: $callbackUrl }) { - nonce { - authUrl - } - } -} diff --git a/lib/registry/graphql/mutations/publish_deploy_app.graphql b/lib/registry/graphql/mutations/publish_deploy_app.graphql deleted file mode 100644 index 123843dd1b7..00000000000 --- a/lib/registry/graphql/mutations/publish_deploy_app.graphql +++ /dev/null @@ -1,16 +0,0 @@ -mutation PublishDeployApp($config: JSONString!, $name: ID, $owner: ID) { - publishDeployApp(input: { config: $config, name: $name, owner: $owner }) { - deployAppVersion { - id - version - app { - id - owner { - __typename - globalName - } - name - } - } - } -} diff --git a/lib/registry/graphql/mutations/publish_package_chunked.graphql b/lib/registry/graphql/mutations/publish_package_chunked.graphql deleted file mode 100644 index 0537e5a47e2..00000000000 --- a/lib/registry/graphql/mutations/publish_package_chunked.graphql +++ /dev/null @@ -1,50 +0,0 @@ -mutation PublishPackageMutationChunked( - $name: String - $namespace: String - $version: String - $description: String - $manifest: String! - $license: String - $licenseFile: String - $readme: String - $fileName: String - $repository: String - $homepage: String - $signature: InputSignature - $signedUrl: String - $private: Boolean - $wait: Boolean -) { - publishPackage( - input: { - name: $name - namespace: $namespace - version: $version - description: $description - manifest: $manifest - license: $license - licenseFile: $licenseFile - readme: $readme - file: $fileName - signedUrl: $signedUrl - repository: $repository - homepage: $homepage - signature: $signature - clientMutationId: "" - private: $private - wait: $wait - } - ) { - success - packageVersion { - id - version - } - - packageWebc { - webcV3 { - webcSha256 - } - } - } -} diff --git a/lib/registry/graphql/queries/get_bindings.graphql b/lib/registry/graphql/queries/get_bindings.graphql deleted file mode 100644 index 9a8cbe7a3da..00000000000 --- a/lib/registry/graphql/queries/get_bindings.graphql +++ /dev/null @@ -1,22 +0,0 @@ -query GetBindingsQuery($name: String!, $version: String = "latest") { - packageVersion: getPackageVersion(name: $name, version: $version) { - bindings { - id - language - url - - generator { - packageVersion { - id - version - package { - name - } - } - commandName - } - - __typename - } - } -} diff --git a/lib/registry/graphql/queries/get_interface_version.graphql b/lib/registry/graphql/queries/get_interface_version.graphql deleted file mode 100644 index 48508aaad83..00000000000 --- a/lib/registry/graphql/queries/get_interface_version.graphql +++ /dev/null @@ -1,9 +0,0 @@ -query GetInterfaceVersionQuery($name: String!, $version: String!) { - interface: getInterfaceVersion(name: $name, version: $version) { - version - content - interface { - name - } - } -} diff --git a/lib/registry/graphql/queries/get_package_by_command.graphql b/lib/registry/graphql/queries/get_package_by_command.graphql deleted file mode 100644 index 8511d47a1f8..00000000000 --- a/lib/registry/graphql/queries/get_package_by_command.graphql +++ /dev/null @@ -1,18 +0,0 @@ -query GetPackageByCommandQuery($commandName: String!) { - getCommand(name: $commandName) { - command - packageVersion { - version - isLastVersion - manifest - distribution { - downloadUrl - piritaDownloadUrl - } - package { - displayName - private - } - } - } -} diff --git a/lib/registry/graphql/queries/get_package_version.graphql b/lib/registry/graphql/queries/get_package_version.graphql deleted file mode 100644 index 751c3b40d48..00000000000 --- a/lib/registry/graphql/queries/get_package_version.graphql +++ /dev/null @@ -1,15 +0,0 @@ -query GetPackageVersionQuery($name: String!, $version: String) { - packageVersion: getPackageVersion(name: $name, version: $version) { - package { - name - private - } - version - isLastVersion - distribution { - downloadUrl - piritaDownloadUrl - } - manifest - } -} diff --git a/lib/registry/graphql/queries/get_signed_url.graphql b/lib/registry/graphql/queries/get_signed_url.graphql deleted file mode 100644 index a4aacb0b82c..00000000000 --- a/lib/registry/graphql/queries/get_signed_url.graphql +++ /dev/null @@ -1,15 +0,0 @@ -query GetSignedUrl( - $name: String - $version: String - $filename: String - $expiresAfterSeconds: Int -) { - url: getSignedUrlForPackageUpload( - name: $name - version: $version - filename: $filename - expiresAfterSeconds: $expiresAfterSeconds - ) { - url - } -} diff --git a/lib/registry/graphql/queries/test_if_registry_present.graphql b/lib/registry/graphql/queries/test_if_registry_present.graphql deleted file mode 100644 index 61c21522e41..00000000000 --- a/lib/registry/graphql/queries/test_if_registry_present.graphql +++ /dev/null @@ -1,3 +0,0 @@ -query TestIfRegistryPresent { - __typename -} diff --git a/lib/registry/graphql/queries/whoami.graphql b/lib/registry/graphql/queries/whoami.graphql deleted file mode 100644 index 256c983a158..00000000000 --- a/lib/registry/graphql/queries/whoami.graphql +++ /dev/null @@ -1,5 +0,0 @@ -query WhoAmIQuery { - viewer { - username - } -} diff --git a/lib/registry/graphql/schema.graphql b/lib/registry/graphql/schema.graphql deleted file mode 100644 index 82df13b7bda..00000000000 --- a/lib/registry/graphql/schema.graphql +++ /dev/null @@ -1,3974 +0,0 @@ -""" -Directs the executor to include this field or fragment only when the user is not logged in. -""" -directive @includeIfLoggedIn on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - -""" -Directs the executor to skip this field or fragment when the user is not logged in. -""" -directive @skipIfLoggedIn on FIELD | FRAGMENT_SPREAD | INLINE_FRAGMENT - -interface Node { - """The ID of the object""" - id: ID! -} - -type PublicKey implements Node { - """The ID of the object""" - id: ID! - owner: User! - keyId: String! - key: String! - revokedAt: DateTime - uploadedAt: DateTime! - verifyingSignature: Signature - revoked: Boolean! -} - -type User implements Node & PackageOwner & Owner { - firstName: String! - lastName: String! - email: String! - dateJoined: DateTime! - - """Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.""" - username: String! - isEmailValidated: Boolean! - bio: String - location: String - websiteUrl: String - - """The ID of the object""" - id: ID! - globalName: String! - globalId: ID! - avatar(size: Int = 80): String! - isViewer: Boolean! - hasUsablePassword: Boolean - fullName: String! - githubUrl: String - twitterUrl: String - companyRole: String - companyDescription: String - publicActivity(offset: Int, before: String, after: String, first: Int, last: Int): ActivityEventConnection! - billing: Billing - waitlist(name: String!): WaitlistMember - namespaces(role: GrapheneRole, offset: Int, before: String, after: String, first: Int, last: Int): NamespaceConnection! - packages(collaborating: Boolean = false, offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection! - apps(collaborating: Boolean = false, sortBy: DeployAppsSortBy, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppConnection! - usageMetrics(forRange: MetricRange!, variant: MetricType!): [UsageMetric]! - domains(offset: Int, before: String, after: String, first: Int, last: Int): DNSDomainConnection! - isStaff: Boolean - packageVersions(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! - packageTransfersIncoming(offset: Int, before: String, after: String, first: Int, last: Int): PackageTransferRequestConnection! - packageInvitesIncoming(offset: Int, before: String, after: String, first: Int, last: Int): PackageCollaboratorInviteConnection! - namespaceInvitesIncoming(offset: Int, before: String, after: String, first: Int, last: Int): NamespaceCollaboratorInviteConnection! - apiTokens(before: String, after: String, first: Int, last: Int): APITokenConnection! - notifications(before: String, after: String, first: Int, last: Int): UserNotificationConnection! - dashboardActivity(offset: Int, before: String, after: String, first: Int, last: Int): ActivityEventConnection! - loginMethods: [LoginMethod!]! - githubUser: SocialAuth - githubScopes: [String]! -} - -"""Setup for backwards compatibility with existing frontends.""" -interface PackageOwner { - globalName: String! - globalId: ID! -} - -"""An owner of a package.""" -interface Owner { - globalName: String! - globalId: ID! -} - -""" -The `DateTime` scalar type represents a DateTime -value as specified by -[iso8601](https://en.wikipedia.org/wiki/ISO_8601). -""" -scalar DateTime - -type ActivityEventConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [ActivityEventEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -""" -The Relay compliant `PageInfo` type, containing data necessary to paginate this connection. -""" -type PageInfo { - """When paginating forwards, are there more items?""" - hasNextPage: Boolean! - - """When paginating backwards, are there more items?""" - hasPreviousPage: Boolean! - - """When paginating backwards, the cursor to continue.""" - startCursor: String - - """When paginating forwards, the cursor to continue.""" - endCursor: String -} - -"""A Relay edge containing a `ActivityEvent` and its cursor.""" -type ActivityEventEdge { - """The item at the end of the edge""" - node: ActivityEvent - - """A cursor for use in pagination""" - cursor: String! -} - -type ActivityEvent implements Node { - """The ID of the object""" - id: ID! - body: EventBody! - actorIcon: String! - createdAt: DateTime! -} - -type EventBody { - text: String! - ranges: [NodeBodyRange!]! -} - -type NodeBodyRange { - entity: Node! - offset: Int! - length: Int! -} - -type WaitlistMember implements Node { - waitlist: Waitlist! - joinedAt: DateTime! - approvedAt: DateTime - - """The ID of the object""" - id: ID! - member: Owner! - approved: Boolean! -} - -type Waitlist implements Node { - name: String! - createdAt: DateTime! - updatedAt: DateTime! - - """The ID of the object""" - id: ID! -} - -type NamespaceConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [NamespaceEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `Namespace` and its cursor.""" -type NamespaceEdge { - """The item at the end of the edge""" - node: Namespace - - """A cursor for use in pagination""" - cursor: String! -} - -type Namespace implements Node & PackageOwner & Owner { - """The ID of the object""" - id: ID! - name: String! - displayName: String - description: String! - avatar: String! - avatarUpdatedAt: DateTime - twitterHandle: String - githubHandle: String - websiteUrl: String - createdAt: DateTime! - updatedAt: DateTime! - maintainerInvites(offset: Int, before: String, after: String, first: Int, last: Int): NamespaceCollaboratorInviteConnection! - userSet(offset: Int, before: String, after: String, first: Int, last: Int): UserConnection! - globalName: String! - globalId: ID! - packages(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection! - apps(sortBy: DeployAppsSortBy, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppConnection! - packageVersions(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! - collaborators(offset: Int, before: String, after: String, first: Int, last: Int): NamespaceCollaboratorConnection! - publicActivity(before: String, after: String, first: Int, last: Int): ActivityEventConnection! - pendingInvites(offset: Int, before: String, after: String, first: Int, last: Int): NamespaceCollaboratorInviteConnection! - viewerHasRole(role: GrapheneRole!): Boolean! - viewerAsCollaborator(role: GrapheneRole): NamespaceCollaborator - - """Whether the current user is invited to the namespace""" - viewerIsInvited: Boolean! - - """The invitation for the current user to the namespace""" - viewerInvitation: NamespaceCollaboratorInvite - packageTransfersIncoming(offset: Int, before: String, after: String, first: Int, last: Int): PackageTransferRequestConnection! - usageMetrics(forRange: MetricRange!, variant: MetricType!): [UsageMetric]! - domains(offset: Int, before: String, after: String, first: Int, last: Int): DNSDomainConnection! -} - -type NamespaceCollaboratorInviteConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [NamespaceCollaboratorInviteEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -""" -A Relay edge containing a `NamespaceCollaboratorInvite` and its cursor. -""" -type NamespaceCollaboratorInviteEdge { - """The item at the end of the edge""" - node: NamespaceCollaboratorInvite - - """A cursor for use in pagination""" - cursor: String! -} - -type NamespaceCollaboratorInvite implements Node { - """The ID of the object""" - id: ID! - requestedBy: User! - user: User - inviteEmail: String - namespace: Namespace! - role: RegistryNamespaceMaintainerInviteRoleChoices! - accepted: NamespaceCollaborator - approvedBy: User - declinedBy: User - createdAt: DateTime! - expiresAt: DateTime! - closedAt: DateTime -} - -enum RegistryNamespaceMaintainerInviteRoleChoices { - """Owner""" - OWNER - - """Admin""" - ADMIN - - """Editor""" - EDITOR - - """Viewer""" - VIEWER -} - -type NamespaceCollaborator implements Node { - """The ID of the object""" - id: ID! - user: User! - role: RegistryNamespaceMaintainerRoleChoices! - namespace: Namespace! - createdAt: DateTime! - updatedAt: DateTime! - invite: NamespaceCollaboratorInvite -} - -enum RegistryNamespaceMaintainerRoleChoices { - """Owner""" - OWNER - - """Admin""" - ADMIN - - """Editor""" - EDITOR - - """Viewer""" - VIEWER -} - -type UserConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [UserEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `User` and its cursor.""" -type UserEdge { - """The item at the end of the edge""" - node: User - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `Package` and its cursor.""" -type PackageEdge { - """The item at the end of the edge""" - node: Package - - """A cursor for use in pagination""" - cursor: String! -} - -type Package implements Likeable & Node & PackageOwner { - """The ID of the object""" - id: ID! - name: String! - private: Boolean! - createdAt: DateTime! - updatedAt: DateTime! - maintainers: [User]! @deprecated(reason: "Please use collaborators instead") - curated: Boolean! - ownerObjectId: Int! - lastVersion: PackageVersion - - """The app icon. It should be formatted in the same way as Apple icons""" - icon: String! - totalDownloads: Int! - iconUpdatedAt: DateTime - watchersCount: Int! - webcs(offset: Int, before: String, after: String, first: Int, last: Int): WebcImageConnection! - - """List of app templates for this package""" - appTemplates(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection! - packagewebcSet(offset: Int, before: String, after: String, first: Int, last: Int): PackageWebcConnection! - versions: [PackageVersion]! - collectionSet: [Collection!]! - categories(offset: Int, before: String, after: String, first: Int, last: Int): CategoryConnection! - keywords(offset: Int, before: String, after: String, first: Int, last: Int): PackageKeywordConnection! - likersCount: Int! - viewerHasLiked: Boolean! - globalName: String! - globalId: ID! - alias: String - namespace: String! - displayName: String! - - """The name of the package without the owner""" - packageName: String! - - """The app icon. It should be formatted in the same way as Apple icons""" - appIcon: String! @deprecated(reason: "Please use icon instead") - - """The total number of downloads of the package""" - downloadsCount: Int - - """The public keys for all the published versions""" - publicKeys: [PublicKey!]! - collaborators(offset: Int, before: String, after: String, first: Int, last: Int): PackageCollaboratorConnection! - pendingInvites(offset: Int, before: String, after: String, first: Int, last: Int): PackageCollaboratorInviteConnection! - viewerHasRole(role: GrapheneRole!): Boolean! - viewerAsCollaborator(role: GrapheneRole): PackageCollaborator - owner: PackageOwner! - isTransferring: Boolean! - activeTransferRequest: PackageTransferRequest - isArchived: Boolean! - viewerIsWatching: Boolean! - showDeployButton: Boolean! - similarPackageVersions(before: String, after: String, first: Int, last: Int): PackageSearchConnection! - - """Whether the current user is invited to the package""" - viewerIsInvited: Boolean! - - """The invitation for the current user to the package""" - viewerInvitation: PackageCollaboratorInvite -} - -interface Likeable { - id: ID! - likersCount: Int! - viewerHasLiked: Boolean! -} - -type PackageVersion implements Node & PackageReleaseInterface & PackageInstance { - """The ID of the object""" - id: ID! - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - package: Package! - webc: WebcImage - webcV3: WebcImage - - """List of direct dependencies of this package version""" - dependencies(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! - publishedBy: User! - tag: String! - clientName: String - webcGenerationErrors: String - version: String! - description: String! - manifest: String! - license: String - licenseFile: String - readme: String - witMd: String - repository: String - homepage: String - staticObjectsCompiled: Boolean! - nativeExecutablesCompiled: Boolean! - signature: Signature - isArchived: Boolean! - file: String! - - """""" - fileSize: BigInt! - totalDownloads: Int! - bindingsState: RegistryPackageVersionBindingsStateChoices! - nativeExecutablesState: RegistryPackageVersionNativeExecutablesStateChoices! - deployappversionSet(offset: Int, before: String, after: String, first: Int, last: Int): DeployAppVersionConnection! - lastversionPackage(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection! - commands: [Command!]! - nativeexecutableSet(offset: Int, before: String, after: String, first: Int, last: Int): NativeExecutableConnection! - bindingsgeneratorSet(offset: Int, before: String, after: String, first: Int, last: Int): BindingsGeneratorConnection! - javascriptlanguagebindingSet(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionNPMBindingConnection! - pythonlanguagebindingSet(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionPythonBindingConnection! - piritaManifest: JSONString - piritaOffsets: JSONString - piritaVolumes: JSONString - piritaFile: String @deprecated(reason: "Please use distribution.piritaDownloadUrl instead.") - piritaFileSize: Int @deprecated(reason: "Please use distribution.piritaSize instead.") - pirita256hash: String @deprecated(reason: "Please use distribution.piritaSha256Hash instead.") - distribution(version: WebcVersion): PackageDistribution! - filesystem: [PackageVersionFilesystem]! - isLastVersion: Boolean! - witFile: String - isSigned: Boolean! - moduleInterfaces: [InterfaceVersion!]! - modules: [PackageVersionModule!]! - getPiritaContents(volume: String! = "atom", base: String! = ""): [PiritaFilesystemItem!]! - getWebcContents(volume: String! = "atom", base: String! = "/"): [WEBCFilesystemItem!]! - nativeExecutables(triple: String, wasmerCompilerVersion: String): [NativeExecutable] - bindings: [PackageVersionLanguageBinding]! - npmBindings: PackageVersionNPMBinding - pythonBindings: PackageVersionPythonBinding - bindingsSet(before: String, after: String, first: Int, last: Int): PackageVersionBindingConnection - hasBindings: Boolean! - hasCommands: Boolean! - showDeployButton: Boolean! - isCorrupt: Boolean! -} - -interface PackageReleaseInterface { - piritaManifest: JSONString - piritaOffsets: JSONString - piritaVolumes: JSONString - isArchived: Boolean! - clientName: String - publishedBy: User! - createdAt: DateTime! - updatedAt: DateTime! - package: Package! - webc: WebcImage - webcV3: WebcImage - tag: String! -} - -""" -Allows use of a JSON String for input / output from the GraphQL schema. - -Use of this type is *not recommended* as you lose the benefits of having a defined, static -schema (one of the key benefits of GraphQL). -""" -scalar JSONString - -type WebcImage implements Node { - """The ID of the object""" - id: ID! - version: RegistryWebcImageVersionChoices! - - """""" - fileSize: BigInt! - manifest: JSONString! - volumes: JSONString! - offsets: JSONString! - webcSha256: String! - targzSha256: String - createdAt: DateTime! - updatedAt: DateTime! - webcUrl: String! -} - -enum RegistryWebcImageVersionChoices { - """v2""" - V2 - - """v3""" - V3 -} - -""" -The `BigInt` scalar type represents non-fractional whole numeric values. -`BigInt` is not constrained to 32-bit like the `Int` type and thus is a less -compatible type. -""" -scalar BigInt - -type PackageVersionConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageVersionEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageVersion` and its cursor.""" -type PackageVersionEdge { - """The item at the end of the edge""" - node: PackageVersion - - """A cursor for use in pagination""" - cursor: String! -} - -enum RegistryPackageVersionBindingsStateChoices { - """Bindings are not detected""" - NOT_PRESENT - - """Bindings are being built""" - GENERATING - - """Bindings generation has failed""" - ERROR - - """Bindings are built and present""" - GENERATED_AND_PRESENT -} - -enum RegistryPackageVersionNativeExecutablesStateChoices { - """Native Executables are not detected""" - NOT_PRESENT - - """Native Executables are being built""" - GENERATING - - """Native Executables generation has failed""" - ERROR - - """Native Executables are built and present""" - GENERATED_AND_PRESENT -} - -type DeployAppVersionConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [DeployAppVersionEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `DeployAppVersion` and its cursor.""" -type DeployAppVersionEdge { - """The item at the end of the edge""" - node: DeployAppVersion - - """A cursor for use in pagination""" - cursor: String! -} - -type DeployAppVersion implements Node { - """The ID of the object""" - id: ID! - app: DeployApp! - yamlConfig: String! - userYamlConfig: String! - clientName: String! - signature: String - description: String - publishedBy: User! - createdAt: DateTime! - updatedAt: DateTime! - configWebc: String @deprecated(reason: "webc support has been deprecated for apps") - config: String! @deprecated(reason: "Please use jsonConfig instead") - jsonConfig: String! - url: String! - permalink: String! - urls: [String]! - version: String! - isActive: Boolean! - manifest: String! - logs( - """ - Get logs starting from this timestamp. Takes EPOCH timestamp in seconds. - """ - startingFrom: Float - - """Get logs starting from this timestamp. Takes ISO timestamp.""" - startingFromISO: DateTime - - """Fetch logs until this timestamp. Takes EPOCH timestamp in seconds.""" - until: Float - - """List of streams to fetch logs from. e.g. stdout, stderr.""" - streams: [LogStream] - - """List of instance ids to fetch logs from.""" - instanceIds: [String] - before: String - after: String - first: Int - last: Int - ): LogConnection! - usageMetrics(forRange: MetricRange!, variant: MetricType!): [UsageMetric]! - sourcePackageVersion: PackageVersion! - aggregateMetrics: AggregateMetrics! - volumes: [AppVersionVolume] - favicon: URL - screenshot: URL -} - -type DeployApp implements Node & Owner { - """The ID of the object""" - id: ID! - createdBy: User! - createdAt: DateTime! - updatedAt: DateTime! - activeVersion: DeployAppVersion! - globalName: String! - globalId: ID! - url: String! - adminUrl: String! - permalink: String! - urls: [String]! - description: String - name: String! - owner: Owner! - versions(sortBy: DeployAppVersionsSortBy, createdAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppVersionConnection! - aggregateMetrics: AggregateMetrics! - aliases(offset: Int, before: String, after: String, first: Int, last: Int): AppAliasConnection! - usageMetrics(forRange: MetricRange!, variant: MetricType!): [UsageMetric]! - deleted: Boolean! - favicon: URL - screenshot: URL -} - -enum DeployAppVersionsSortBy { - NEWEST - OLDEST -} - -type AggregateMetrics { - cpuTime: String! - memoryTime: String! - ingress: String! - egress: String! - noRequests: String! - noFailedRequests: String! - monthlyCost: String! -} - -type AppAliasConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [AppAliasEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `AppAlias` and its cursor.""" -type AppAliasEdge { - """The item at the end of the edge""" - node: AppAlias - - """A cursor for use in pagination""" - cursor: String! -} - -type AppAlias implements Node { - name: String! - app: DeployApp! - isDefault: Boolean! - hostname: String! - text: String! - kind: DeployAppAliasKindChoices! - - """The ID of the object""" - id: ID! - url: String! -} - -enum DeployAppAliasKindChoices { - """Deployment""" - DEPLOYMENT - - """Domain""" - DOMAIN -} - -type UsageMetric { - variant: MetricType! - value: Float! - unit: MetricUnit! - timestamp: DateTime! -} - -enum MetricType { - cpu_time - memory_time - network_egress - network_ingress - no_of_requests - no_of_failed_requests - cost -} - -"""Units for metrics""" -enum MetricUnit { - """represents the unit of "seconds".""" - SEC - - """represents the unit of "milliseconds".""" - MS - - """represents the unit of "kilobytes".""" - KB - - """represents the unit of "kilobytes per second".""" - KBS - - """represents the unit of "number of requests".""" - NO_REQUESTS - - """represents the unit of "cost" in USD.""" - DOLLARS -} - -enum MetricRange { - LAST_24_HOURS - LAST_30_DAYS - LAST_1_HOUR -} - -""" -The `URL` scalar type represents a URL as text, represented as UTF-8 -character sequences. -""" -scalar URL - -type LogConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [LogEdge]! -} - -"""A Relay edge containing a `Log` and its cursor.""" -type LogEdge { - """The item at the end of the edge""" - node: Log - - """A cursor for use in pagination""" - cursor: String! -} - -enum LogStream { - STDOUT - STDERR - RUNTIME -} - -type AppVersionVolume { - name: String! - mountPaths: [AppVersionVolumeMountPath]! - size: Int - usedSize: Int -} - -type AppVersionVolumeMountPath { - path: String! - subpath: String! -} - -type Command { - command: String! - packageVersion: PackageVersion! - module: PackageVersionModule! -} - -type PackageVersionModule { - name: String! - source: String! - abi: String - publicUrl: String! - atom: PiritaFilesystemFile! - rangeHeader: String! -} - -type PiritaFilesystemFile { - name(display: PiritaFilesystemNameDisplay): String! - size: Int! - offset: Int! -} - -enum PiritaFilesystemNameDisplay { - RELATIVE - ABSOLUTE -} - -type NativeExecutableConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [NativeExecutableEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `NativeExecutable` and its cursor.""" -type NativeExecutableEdge { - """The item at the end of the edge""" - node: NativeExecutable - - """A cursor for use in pagination""" - cursor: String! -} - -type NativeExecutable implements Node { - """The ID of the object""" - id: ID! - module: String! @deprecated(reason: "Use filename instead") - filename: String! - filesize: Int! - targetTriple: String! - downloadUrl: String! -} - -type BindingsGeneratorConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [BindingsGeneratorEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `BindingsGenerator` and its cursor.""" -type BindingsGeneratorEdge { - """The item at the end of the edge""" - node: BindingsGenerator - - """A cursor for use in pagination""" - cursor: String! -} - -type BindingsGenerator implements Node { - """The ID of the object""" - id: ID! - packageVersion: PackageVersion! - active: Boolean! - commandName: String! - registryJavascriptlanguagebindings(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionNPMBindingConnection! - registryPythonlanguagebindings(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionPythonBindingConnection! -} - -type PackageVersionNPMBindingConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageVersionNPMBindingEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageVersionNPMBinding` and its cursor.""" -type PackageVersionNPMBindingEdge { - """The item at the end of the edge""" - node: PackageVersionNPMBinding - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageVersionNPMBinding implements PackageVersionLanguageBinding & Node { - """The ID of the object""" - id: ID! - language: ProgrammingLanguage! - - """The URL of the generated artifacts on Wasmer CDN.""" - url: String! - - """When the binding was generated""" - createdAt: DateTime! - - """Package version used to generate this binding""" - generator: BindingsGenerator! - name: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - kind: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - - """Name of package source""" - packageName: String! - - """Name of the package to import""" - importablePackageName: String! - - """Code snippet example to use the package""" - codeSnippetExample: String! - module: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - npmDefaultInstallPackageName(url: String): String! @deprecated(reason: "Please use packageName instead") -} - -interface PackageVersionLanguageBinding { - id: ID! - language: ProgrammingLanguage! - - """The URL of the generated artifacts on Wasmer CDN.""" - url: String! - - """When the binding was generated""" - createdAt: DateTime! - - """Package version used to generate this binding""" - generator: BindingsGenerator! - name: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - kind: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - - """Name of package source""" - packageName: String! - - """Name of the package to import""" - importablePackageName: String! - - """Code snippet example to use the package""" - codeSnippetExample: String! - module: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") -} - -enum ProgrammingLanguage { - PYTHON - JAVASCRIPT -} - -type PackageVersionPythonBindingConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageVersionPythonBindingEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -""" -A Relay edge containing a `PackageVersionPythonBinding` and its cursor. -""" -type PackageVersionPythonBindingEdge { - """The item at the end of the edge""" - node: PackageVersionPythonBinding - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageVersionPythonBinding implements PackageVersionLanguageBinding & Node { - """The ID of the object""" - id: ID! - language: ProgrammingLanguage! - - """The URL of the generated artifacts on Wasmer CDN.""" - url: String! - - """When the binding was generated""" - createdAt: DateTime! - - """Package version used to generate this binding""" - generator: BindingsGenerator! - name: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - kind: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - - """Name of package source""" - packageName: String! - - """Name of the package to import""" - importablePackageName: String! - - """Code snippet example to use the package""" - codeSnippetExample: String! - module: String! @deprecated(reason: "Do not use this field, since bindings for all modules are generated at once now.") - pythonDefaultInstallPackageName(url: String): String! -} - -type PackageDistribution { - """ - Download URL of the tar.gz file. - If the package was published with webc only,this will contain download URL for webc file instead. - """ - downloadUrl: String! - expiresInSeconds: Int - size: Int - piritaDownloadUrl: String - piritaExpiresInSeconds: Int - piritaSize: Int - piritaSha256Hash: String - webcDownloadUrl: String - webcExpiresInSeconds: Int - webcSize: Int - webcSha256Hash: String - webcVersion: WebcVersion -} - -enum WebcVersion { - V2 - V3 -} - -type PackageVersionFilesystem { - wasm: String! - host: String! -} - -type InterfaceVersion implements Node { - """The ID of the object""" - id: ID! - interface: Interface! - version: String! - content: String! - createdAt: DateTime! - updatedAt: DateTime! - publishedBy: User! - packageVersions(offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! -} - -type Interface implements Node { - """The ID of the object""" - id: ID! - name: String! - displayName: String! - description: String! - homepage: String - icon: String - createdAt: DateTime! - updatedAt: DateTime! - versions(offset: Int, before: String, after: String, first: Int, last: Int): InterfaceVersionConnection! - lastVersion: InterfaceVersion -} - -type InterfaceVersionConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [InterfaceVersionEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `InterfaceVersion` and its cursor.""" -type InterfaceVersionEdge { - """The item at the end of the edge""" - node: InterfaceVersion - - """A cursor for use in pagination""" - cursor: String! -} - -union PiritaFilesystemItem = PiritaFilesystemFile | PiritaFilesystemDir - -type PiritaFilesystemDir { - name(display: PiritaFilesystemNameDisplay): String! -} - -type WEBCFilesystemItem { - name: String! - checksum: String! - size: Int! - offset: Int! -} - -type PackageVersionBindingConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageVersionBindingEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageVersionBinding` and its cursor.""" -type PackageVersionBindingEdge { - """The item at the end of the edge""" - node: PackageVersionBinding - - """A cursor for use in pagination""" - cursor: String! -} - -union PackageVersionBinding = PackageVersionNPMBinding | PackageVersionPythonBinding - -type WebcImageConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [WebcImageEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `WebcImage` and its cursor.""" -type WebcImageEdge { - """The item at the end of the edge""" - node: WebcImage - - """A cursor for use in pagination""" - cursor: String! -} - -type AppTemplateConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [AppTemplateEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `AppTemplate` and its cursor.""" -type AppTemplateEdge { - """The item at the end of the edge""" - node: AppTemplate - - """A cursor for use in pagination""" - cursor: String! -} - -type AppTemplate implements Node { - """The ID of the object""" - id: ID! - name: String! - slug: String! - description: String! - demoUrl: String! - repoUrl: String! - category: AppTemplateCategory! - isPublic: Boolean! - createdAt: DateTime! - updatedAt: DateTime! - readme: String! - useCases: JSONString! - framework: String! - language: String! - repoLicense: String! - usingPackage: Package - defaultImage: String -} - -type AppTemplateCategory implements Node { - """The ID of the object""" - id: ID! - name: String! - slug: String! - description: String! - createdAt: DateTime! - updatedAt: DateTime! - appTemplates(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection! -} - -type PackageWebcConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageWebcEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageWebc` and its cursor.""" -type PackageWebcEdge { - """The item at the end of the edge""" - node: PackageWebc - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageWebc implements Node & PackageReleaseInterface & PackageInstance { - """The ID of the object""" - id: ID! - createdAt: DateTime! - updatedAt: DateTime! - package: Package! - webc: WebcImage - piritaManifest: JSONString - piritaOffsets: JSONString - piritaVolumes: JSONString - isArchived: Boolean! - clientName: String - publishedBy: User! - webcV3: WebcImage - tag: String! - webcUrl: String! -} - -type Collection { - slug: String! - displayName: String! - description: String! - createdAt: DateTime! - banner: String! - packages(before: String, after: String, first: Int, last: Int): PackageConnection! -} - -type CategoryConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [CategoryEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `Category` and its cursor.""" -type CategoryEdge { - """The item at the end of the edge""" - node: Category - - """A cursor for use in pagination""" - cursor: String! -} - -type Category implements Node { - """The ID of the object""" - id: ID! - - """A category is a label that can be attached to a package.""" - name: String! - packages(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection -} - -type PackageKeywordConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageKeywordEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageKeyword` and its cursor.""" -type PackageKeywordEdge { - """The item at the end of the edge""" - node: PackageKeyword - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageKeyword implements Node { - """The ID of the object""" - id: ID! - name: String! -} - -type PackageCollaboratorConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageCollaboratorEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageCollaborator` and its cursor.""" -type PackageCollaboratorEdge { - """The item at the end of the edge""" - node: PackageCollaborator - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageCollaborator implements Node { - """The ID of the object""" - id: ID! - user: User! - role: RegistryPackageMaintainerRoleChoices! - package: Package! - createdAt: DateTime! - updatedAt: DateTime! - invite: PackageCollaboratorInvite -} - -enum RegistryPackageMaintainerRoleChoices { - """Owner""" - OWNER - - """Admin""" - ADMIN - - """Editor""" - EDITOR - - """Viewer""" - VIEWER -} - -type PackageCollaboratorInvite implements Node { - """The ID of the object""" - id: ID! - requestedBy: User! - user: User - inviteEmail: String - package: Package! - role: RegistryPackageMaintainerInviteRoleChoices! - accepted: PackageCollaborator - approvedBy: User - declinedBy: User - createdAt: DateTime! - expiresAt: DateTime! - closedAt: DateTime -} - -enum RegistryPackageMaintainerInviteRoleChoices { - """Owner""" - OWNER - - """Admin""" - ADMIN - - """Editor""" - EDITOR - - """Viewer""" - VIEWER -} - -type PackageCollaboratorInviteConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageCollaboratorInviteEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageCollaboratorInvite` and its cursor.""" -type PackageCollaboratorInviteEdge { - """The item at the end of the edge""" - node: PackageCollaboratorInvite - - """A cursor for use in pagination""" - cursor: String! -} - -enum GrapheneRole { - OWNER - ADMIN - EDITOR - VIEWER -} - -type PackageTransferRequest implements Node { - """The ID of the object""" - id: ID! - requestedBy: User! - previousOwnerObjectId: Int! - newOwnerObjectId: Int! - package: Package! - approvedBy: User - declinedBy: User - createdAt: DateTime! - expiresAt: DateTime! - closedAt: DateTime - previousOwner: PackageOwner! - newOwner: PackageOwner! -} - -type PackageSearchConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageSearchEdge]! - totalCount: Int -} - -"""A Relay edge containing a `PackageSearch` and its cursor.""" -type PackageSearchEdge { - """The item at the end of the edge""" - node: PackageVersion - - """A cursor for use in pagination""" - cursor: String! -} - -type DeployAppConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [DeployAppEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `DeployApp` and its cursor.""" -type DeployAppEdge { - """The item at the end of the edge""" - node: DeployApp - - """A cursor for use in pagination""" - cursor: String! -} - -enum DeployAppsSortBy { - NEWEST - OLDEST - MOST_ACTIVE -} - -type NamespaceCollaboratorConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [NamespaceCollaboratorEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `NamespaceCollaborator` and its cursor.""" -type NamespaceCollaboratorEdge { - """The item at the end of the edge""" - node: NamespaceCollaborator - - """A cursor for use in pagination""" - cursor: String! -} - -type PackageTransferRequestConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [PackageTransferRequestEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `PackageTransferRequest` and its cursor.""" -type PackageTransferRequestEdge { - """The item at the end of the edge""" - node: PackageTransferRequest - - """A cursor for use in pagination""" - cursor: String! -} - -type DNSDomainConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [DNSDomainEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `DNSDomain` and its cursor.""" -type DNSDomainEdge { - """The item at the end of the edge""" - node: DNSDomain - - """A cursor for use in pagination""" - cursor: String! -} - -type DNSDomain implements Node { - name: String! - - """This zone will be accessible at /dns/{slug}/.""" - slug: String! - zoneFile: String! - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - - """The ID of the object""" - id: ID! - records: [DNSRecord] - owner: Owner! -} - -union DNSRecord = ARecord | AAAARecord | CNAMERecord | TXTRecord | MXRecord | NSRecord | CAARecord | DNAMERecord | PTRRecord | SOARecord | SRVRecord | SSHFPRecord - -type ARecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - address: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -interface DNSRecordInterface { - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime -} - -type AAAARecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - address: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type CNAMERecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - - """This domain name will alias to this canonical name.""" - cName: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type TXTRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - data: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type MXRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - preference: Int! - exchange: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type NSRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - nsdname: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type CAARecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - flags: Int! - tag: DnsmanagerCertificationAuthorityAuthorizationRecordTagChoices! - value: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -enum DnsmanagerCertificationAuthorityAuthorizationRecordTagChoices { - """issue""" - ISSUE - - """issue wildcard""" - ISSUEWILD - - """Incident object description exchange format""" - IODEF -} - -type DNAMERecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - - """ - This domain name will alias to the entire subtree of that delegation domain. - """ - dName: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type PTRRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - ptrdname: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type SOARecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - - """Primary master name server for this zone.""" - mname: String! - - """Email address of the administrator responsible for this zone.""" - rname: String! - - """ - A slave name server will initiate a zone transfer if this serial is incremented. - """ - serial: BigInt! - - """ - Number of seconds after which secondary name servers should query the master to detect zone changes. - """ - refresh: BigInt! - - """ - Number of seconds after which secondary name servers should retry to request the serial number from the master if the master does not respond. - """ - retry: BigInt! - - """ - Number of seconds after which secondary name servers should stop answering request for this zone if the master does not respond. - """ - expire: BigInt! - - """Time to live for purposes of negative caching.""" - minimum: BigInt! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type SRVRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - - """The symbolic name of the desired service.""" - service: String! - - """ - The transport protocol of the desired service, usually either TCP or UDP. - """ - protocol: String! - - """The priority of the target host, lower value means more preferred.""" - priority: Int! - - """ - A relative weight for records with the same priority, higher value means higher chance of getting picked. - """ - weight: Int! - port: Int! - - """ - The canonical hostname of the machine providing the service, ending in a dot. - """ - target: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -type SSHFPRecord implements Node & DNSRecordInterface { - createdAt: DateTime! - updatedAt: DateTime! - deletedAt: DateTime - algorithm: DnsmanagerSshFingerprintRecordAlgorithmChoices! - type: DnsmanagerSshFingerprintRecordTypeChoices! - fingerprint: String! - - """The ID of the object""" - id: ID! - name: String! - ttl: Int! - dnsClass: String - text: String! - domain: DNSDomain! -} - -enum DnsmanagerSshFingerprintRecordAlgorithmChoices { - """RSA""" - A_1 - - """DSA""" - A_2 - - """ECDSA""" - A_3 - - """Ed25519""" - A_4 -} - -enum DnsmanagerSshFingerprintRecordTypeChoices { - """SHA-1""" - A_1 - - """SHA-256""" - A_2 -} - -type APITokenConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [APITokenEdge]! -} - -"""A Relay edge containing a `APIToken` and its cursor.""" -type APITokenEdge { - """The item at the end of the edge""" - node: APIToken - - """A cursor for use in pagination""" - cursor: String! -} - -type APIToken { - id: ID! - user: User! - identifier: String - createdAt: DateTime! - revokedAt: DateTime - lastUsedAt: DateTime - nonceSet(offset: Int, before: String, after: String, first: Int, last: Int): NonceConnection! -} - -type NonceConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [NonceEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `Nonce` and its cursor.""" -type NonceEdge { - """The item at the end of the edge""" - node: Nonce - - """A cursor for use in pagination""" - cursor: String! -} - -type Nonce implements Node { - """The ID of the object""" - id: ID! - name: String! - callbackUrl: String! - createdAt: DateTime! - isValidated: Boolean! - secret: String! - token: String! - expired: Boolean! - authUrl: String! -} - -type UserNotificationConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [UserNotificationEdge]! - hasPendingNotifications: Boolean! - pendingNotificationsCount: Int! -} - -"""A Relay edge containing a `UserNotification` and its cursor.""" -type UserNotificationEdge { - """The item at the end of the edge""" - node: UserNotification - - """A cursor for use in pagination""" - cursor: String! -} - -type UserNotification implements Node { - """The ID of the object""" - id: ID! - icon: String - body: EventBody! - seenState: UserNotificationSeenState! - kind: UserNotificationKind - createdAt: DateTime! -} - -enum UserNotificationSeenState { - UNSEEN - SEEN - SEEN_AND_READ -} - -union UserNotificationKind = UserNotificationKindPublishedPackageVersion | UserNotificationKindIncomingPackageTransfer | UserNotificationKindIncomingPackageInvite | UserNotificationKindIncomingNamespaceInvite | UserNotificationKindValidateEmail - -type UserNotificationKindPublishedPackageVersion { - packageVersion: PackageVersion! -} - -type UserNotificationKindIncomingNamespaceInvite { - namespaceInvite: NamespaceCollaboratorInvite! -} - -type UserNotificationKindValidateEmail { - user: User! -} - -""" - - Enum of ways a user can login. One user can have many login methods - associated with their account. - -""" -enum LoginMethod { - GOOGLE - GITHUB - PASSWORD -} - -type SocialAuth implements Node { - """The ID of the object""" - id: ID! - user: User! - provider: String! - uid: String! - extraData: JSONString! - created: DateTime! - modified: DateTime! - username: String! -} - -type Signature { - id: ID! - publicKey: PublicKey! - data: String! - createdAt: DateTime! -} - -type StripeCustomer { - id: ID! -} - -type Billing { - stripeCustomer: StripeCustomer! - payments: [PaymentIntent]! - paymentMethods: [PaymentMethod]! -} - -type PaymentIntent implements Node { - """The datetime this object was created in stripe.""" - created: DateTime - - """Three-letter ISO currency code""" - currency: String! - - """ - Status of this PaymentIntent, one of requires_payment_method, requires_confirmation, requires_action, processing, requires_capture, canceled, or succeeded. You can read more about PaymentIntent statuses here. - """ - status: DjstripePaymentIntentStatusChoices! - - """The ID of the object""" - id: ID! - amount: String! -} - -enum DjstripePaymentIntentStatusChoices { - """ - Cancellation invalidates the intent for future confirmation and cannot be undone. - """ - CANCELED - - """Required actions have been handled.""" - PROCESSING - - """Payment Method require additional action, such as 3D secure.""" - REQUIRES_ACTION - - """Capture the funds on the cards which have been put on holds.""" - REQUIRES_CAPTURE - - """Intent is ready to be confirmed.""" - REQUIRES_CONFIRMATION - - """Intent created and requires a Payment Method to be attached.""" - REQUIRES_PAYMENT_METHOD - - """The funds are in your account.""" - SUCCEEDED -} - -union PaymentMethod = CardPaymentMethod - -type CardPaymentMethod implements Node { - """The ID of the object""" - id: ID! - brand: CardBrand! - country: String! - expMonth: Int! - expYear: Int! - funding: CardFunding! - last4: String! - isDefault: Boolean! -} - -""" -Card brand. - -Can be amex, diners, discover, jcb, mastercard, unionpay, visa, or unknown. -""" -enum CardBrand { - AMEX - DINERS - DISCOVER - JCB - MASTERCARD - UNIONPAY - VISA - UNKNOWN -} - -""" -Card funding type. - -Can be credit, debit, prepaid, or unknown. -""" -enum CardFunding { - CREDIT - DEBIT - PREPAID - UNKNOWN -} - -type Payment { - id: ID - amount: String - paidOn: DateTime -} - -"""Log entry for deploy app.""" -type Log { - """Timestamp in nanoseconds""" - timestamp: Float! - - """ISO 8601 string in UTC""" - datetime: DateTime! - - """Log message""" - message: String! - - """Log stream""" - stream: LogStream -} - -"""This is for backwards compatibility with the old PackageInstance type.""" -interface PackageInstance { - piritaManifest: JSONString - piritaOffsets: JSONString - piritaVolumes: JSONString - isArchived: Boolean! - clientName: String - publishedBy: User! - createdAt: DateTime! - updatedAt: DateTime! - package: Package! - webc: WebcImage - webcV3: WebcImage - tag: String! -} - -type UserNotificationKindIncomingPackageTransfer { - packageTransferRequest: PackageTransferRequest! -} - -type UserNotificationKindIncomingPackageInvite { - packageInvite: PackageCollaboratorInvite! -} - -input DeploymentV1 { - name: String! - workload: WorkloadV1! -} - -input WorkloadV1 { - capability: CapabilityMapV1 - name: String = null - runner: WorkloadRunnerV1! -} - -input AppV1Spec { - aliases: [String] = [] - workload: WorkloadV2! -} - -input WorkloadV2 { - source: String! -} - -input CapabilityCpuV1 { - maximumThreads: Int - maximumUsage: Int -} - -input FileSystemPermissionsV1 { - delete: Boolean - read: Boolean - write: Boolean -} - -input FileSystemVolumeMountV1 { - path: String! - permissions: [FileSystemPermissionsV1] -} - -input FileSystemVolumeSourceLocalV1 { - maximumSize: String! -} - -input FileSystemVolumeSourceV1 { - local: FileSystemVolumeSourceLocalV1! -} - -input FileSystemVolumeConfigV1 { - mounts: [FileSystemVolumeMountV1]! - name: String! - source: FileSystemVolumeSourceV1! -} - -input CapabilityFileSystemV1 { - volumes: [FileSystemVolumeConfigV1]! -} - -input CapabilityPersistentMemoryV1 { - volumes: [String] -} - -input CapabilityMemorySwapV1 { - maximumSize: String - memoryId: String -} - -input CapabilityNetworkV1 { - egress: NetworkEgressV1 -} - -input NetworkEgressV1 { - enabled: Boolean -} - -input CapabilityNetworkDnsV1 { - enabled: Boolean - servers: [String] - allowedHosts: NetworkDnsAllowedHostsV1 -} - -input NetworkDnsAllowedHostsV1 { - allowAllHosts: Boolean - hosts: [String] - regexPatterns: [String] - wildcardPatterns: [String] -} - -input CapabilityNetworkGatewayV1 { - domains: [String] - enforceHttps: Boolean -} - -input CapabilityMapV1 { - memorySwap: CapabilityCpuV1 -} - -input WebcSourceV1 { - name: String! - namespace: String! - repository: String! = "https://registry.wasmer.wtf" - tag: String - authToken: String -} - -input WorkloadRunnerV1 { - webProxy: RunnerWebProxyV1 - wcgi: RunnerWCGIV1 -} - -"""Run a webassembly file.""" -input RunnerWCGIV1 { - source: WorkloadRunnerWasmSourceV1! - dialect: String -} - -input RunnerWebProxyV1 { - source: WorkloadRunnerWasmSourceV1! -} - -input WorkloadRunnerWasmSourceV1 { - webc: WebcSourceV1! -} - -type Query { - latestTOS: TermsOfService! - getDeployAppVersion(name: String!, owner: String, version: String): DeployAppVersion - getAllDomains(namespace: String, offset: Int, before: String, after: String, first: Int, last: Int): DNSDomainConnection! - getAllDNSRecords(sortBy: DNSRecordsSortBy, updatedAfter: DateTime, before: String, after: String, first: Int, last: Int): DNSRecordConnection! - getDomain(name: String!): DNSDomain - getDeployApp( - name: String! - - """Owner of the app. Defaults to logged in user.""" - owner: String - ): DeployApp - getAppByGlobalAlias(alias: String!): DeployApp - getDeployApps(sortBy: DeployAppsSortBy, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppConnection! - getAppVersions(sortBy: DeployAppVersionsSortBy, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): DeployAppVersionConnection! - getAppTemplates(categorySlug: String, offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateConnection - getAppTemplate(slug: String!): AppTemplate - getAppTemplateCategories(offset: Int, before: String, after: String, first: Int, last: Int): AppTemplateCategoryConnection - viewer: User - getUser(username: String!): User - getPasswordResetToken(token: String!): GetPasswordResetToken - getAuthNonce(name: String!): Nonce - - """Can the logged in user create app templates?""" - canDeployAppToGithub: Boolean! - - """Check if a repo exists in the logged in user's github account.""" - checkRepoExists( - """The namespace of the repo to check.""" - namespace: String! - - """The name of the repo to check.""" - name: String! - ): Boolean! - - """Generate a unique repo name in the logged in user's github account.""" - newRepoName( - """The github namespace of the repo to create the repo in.""" - namespace: String! - - """The template to use.""" - templateSlug: String! - ): String! - packages(offset: Int, before: String, after: String, first: Int, last: Int): PackageConnection - recentPackageVersions(curated: Boolean, offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! - allPackageVersions(sortBy: PackageVersionSortBy, createdAfter: DateTime, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): PackageVersionConnection! - allPackageReleases(sortBy: PackageVersionSortBy, createdAfter: DateTime, updatedAfter: DateTime, offset: Int, before: String, after: String, first: Int, last: Int): PackageWebcConnection! - getWebcImage(hash: String!): WebcImage - getNamespace(name: String!): Namespace - getPackage(name: String!): Package - getPackages(names: [String!]!): [Package]! - getPackageVersion(name: String!, version: String = "latest"): PackageVersion - getPackageVersions(names: [String!]!): [PackageVersion] - getPackageVersionByHash(name: String!, hash: String!): PackageVersion - getInterface(name: String!): Interface - getInterfaces(names: [String!]!): [Interface]! - getInterfaceVersion(name: String!, version: String = "latest"): InterfaceVersion - getContract(name: String!): Interface @deprecated(reason: "Please use getInterface instead") - getContracts(names: [String!]!): [Interface]! @deprecated(reason: "Please use getInterfaces instead") - getContractVersion(name: String!, version: String): InterfaceVersion @deprecated(reason: "Please use getInterfaceVersion instead") - getCommand(name: String!): Command - getCommands(names: [String!]!): [Command] - getCollections(before: String, after: String, first: Int, last: Int): CollectionConnection - getSignedUrlForPackageUpload(name: String, version: String = "latest", filename: String, expiresAfterSeconds: Int = 60): SignedUrl - getPackageHash(name: String, hash: String!): PackageWebc - getPackageRelease(hash: String!): PackageWebc - categories(offset: Int, before: String, after: String, first: Int, last: Int): CategoryConnection! - blogposts(tags: [String!], before: String, after: String, first: Int, last: Int): BlogPostConnection! - getBlogpost(slug: String, featured: Boolean): BlogPost - allBlogpostTags(offset: Int, before: String, after: String, first: Int, last: Int): BlogPostTagConnection - search(query: String!, packages: PackagesFilter, namespaces: NamespacesFilter, users: UsersFilter, apps: AppFilter, blogposts: BlogPostsFilter, appTemplates: AppTemplateFilter, before: String, after: String, first: Int, last: Int): SearchConnection! - searchAutocomplete(kind: [SearchKind!], query: String!, before: String, after: String, first: Int, last: Int): SearchConnection! - getGlobalObject(slug: String!): GlobalObject - node( - """The ID of the object""" - id: ID! - ): Node - nodes(ids: [ID!]!): [Node] - info: RegistryInfo -} - -type TermsOfService implements Node { - """The ID of the object""" - id: ID! - content: String! - createdAt: DateTime! - viewerHasAccepted: Boolean! -} - -type DNSRecordConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [DNSRecordEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `DNSRecord` and its cursor.""" -type DNSRecordEdge { - """The item at the end of the edge""" - node: DNSRecord - - """A cursor for use in pagination""" - cursor: String! -} - -enum DNSRecordsSortBy { - NEWEST - OLDEST -} - -type AppTemplateCategoryConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [AppTemplateCategoryEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `AppTemplateCategory` and its cursor.""" -type AppTemplateCategoryEdge { - """The item at the end of the edge""" - node: AppTemplateCategory - - """A cursor for use in pagination""" - cursor: String! -} - -type GetPasswordResetToken { - valid: Boolean! - user: User -} - -enum PackageVersionSortBy { - NEWEST - OLDEST -} - -type CollectionConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [CollectionEdge]! -} - -"""A Relay edge containing a `Collection` and its cursor.""" -type CollectionEdge { - """The item at the end of the edge""" - node: Collection - - """A cursor for use in pagination""" - cursor: String! -} - -type SignedUrl { - url: String! -} - -type BlogPostConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [BlogPostEdge]! -} - -"""A Relay edge containing a `BlogPost` and its cursor.""" -type BlogPostEdge { - """The item at the end of the edge""" - node: BlogPost - - """A cursor for use in pagination""" - cursor: String! -} - -type BlogPost implements Node { - """The ID of the object""" - id: ID! - live: Boolean! - - """The page title as you'd like it to be seen by the public""" - title: String! - - """ - The name of the page as it will appear in URLs e.g http://domain.com/blog/[my-slug]/ - """ - slug: String! - owner: User - body: String! - publishDate: DateTime - theme: BlogBlogPostThemeChoices! - url: String! - coverImageUrl: String - opengraphImageUrl: String - tagline: String! - relatedArticles: [BlogPost!] - updatedAt: DateTime! - tags: [BlogPostTag!] - editUrl: String -} - -enum BlogBlogPostThemeChoices { - """Green""" - GREEN - - """Purple""" - PURPLE - - """Orange""" - ORANGE - - """Blue""" - BLUE -} - -type BlogPostTag implements Node { - """The ID of the object""" - id: ID! - name: String! - slug: String! -} - -type BlogPostTagConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [BlogPostTagEdge]! - - """Total number of items in the connection.""" - totalCount: Int -} - -"""A Relay edge containing a `BlogPostTag` and its cursor.""" -type BlogPostTagEdge { - """The item at the end of the edge""" - node: BlogPostTag - - """A cursor for use in pagination""" - cursor: String! -} - -type SearchConnection { - """Pagination data for this connection.""" - pageInfo: PageInfo! - - """Contains the nodes in this connection.""" - edges: [SearchEdge]! - totalCount: Int -} - -"""A Relay edge containing a `Search` and its cursor.""" -type SearchEdge { - """The item at the end of the edge""" - node: SearchResult - - """A cursor for use in pagination""" - cursor: String! -} - -union SearchResult = PackageVersion | User | Namespace | DeployApp | BlogPost | AppTemplate - -input PackagesFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Filter packages by being curated.""" - curated: Boolean - - """Filter packages by publish date.""" - publishDate: SearchPublishDate - - """Filter packages by having bindings.""" - hasBindings: Boolean = false - - """Filter packages by being standalone.""" - isStandalone: Boolean = false - - """Filter packages by having commands.""" - hasCommands: Boolean = false - - """Filter packages by interface.""" - withInterfaces: [String] - - """Filter packages by deployable status.""" - deployable: Boolean - - """Filter packages by license.""" - license: String - - """Filter packages created after this date.""" - createdAfter: DateTime - - """Filter packages created before this date.""" - createdBefore: DateTime - - """Filter packages with version published after this date.""" - lastPublishedAfter: DateTime - - """Filter packages with version published before this date.""" - lastPublishedBefore: DateTime - - """Filter packages by size.""" - size: CountFilter - - """Filter packages by download count.""" - downloads: CountFilter - - """Filter packages by like count.""" - likes: CountFilter - - """Filter packages by owner.""" - owner: String - - """Filter packages by published by.""" - publishedBy: String - - """Order packages by field.""" - orderBy: PackageOrderBy = PUBLISHED_DATE -} - -enum SearchOrderSort { - ASC - DESC -} - -enum SearchPublishDate { - LAST_DAY - LAST_WEEK - LAST_MONTH - LAST_YEAR -} - -input CountFilter { - count: Int = 0 - comparison: CountComparison = GREATER_THAN_OR_EQUAL -} - -enum CountComparison { - EQUAL - GREATER_THAN - LESS_THAN - GREATER_THAN_OR_EQUAL - LESS_THAN_OR_EQUAL -} - -enum PackageOrderBy { - ALPHABETICALLY - SIZE - TOTAL_DOWNLOADS - PUBLISHED_DATE - CREATED_DATE - TOTAL_LIKES -} - -input NamespacesFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Filter namespaces by package count.""" - packageCount: CountFilter - - """Filter namespaces created after this date.""" - createdAfter: DateTime - - """Filter namespaces created before this date.""" - createdBefore: DateTime - - """Filter namespaces by user count.""" - userCount: CountFilter - - """Filter namespaces by collaborator.""" - collaborator: String - - """Order namespaces by field.""" - orderBy: NamespaceOrderBy = CREATED_DATE -} - -enum NamespaceOrderBy { - PACKAGE_COUNT - COLLABORATOR_COUNT - APP_COUNT - CREATED_DATE -} - -input UsersFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Filter users by package count.""" - packageCount: CountFilter - - """Filter users by namespace count.""" - namespaceCount: CountFilter - - """Filter users joined after this date.""" - joinedAfter: DateTime - - """Filter users joined before this date.""" - joinedBefore: DateTime - - """Order users by field.""" - orderBy: UserOrderBy = CREATED_DATE -} - -enum UserOrderBy { - PACKAGE_COUNT - APP_COUNT - CREATED_DATE -} - -input AppFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Filter apps by deployed by.""" - deployedBy: String - - """Filter apps last deployed after this date.""" - lastDeployedAfter: DateTime - - """Filter apps last deployed before this date.""" - lastDeployedBefore: DateTime - - """Filter apps by owner.""" - owner: String - - """Order apps by field.""" - orderBy: AppOrderBy = CREATED_DATE - - """Filter apps by client name.""" - clientName: String -} - -enum AppOrderBy { - PUBLISHED_DATE - CREATED_DATE -} - -input BlogPostsFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Filter blog posts by tag.""" - tags: [String] -} - -input AppTemplateFilter { - count: Int = 1000 - sortBy: SearchOrderSort = ASC - - """Order app templates by field.""" - orderBy: AppTemplateOrderBy = CREATED_DATE - - """Filter by app template framework""" - framework: String - - """Filter by app template language""" - language: String - - """Filter by one or more of the use-cases for the app template""" - useCases: [String] -} - -enum AppTemplateOrderBy { - CREATED_DATE -} - -enum SearchKind { - PACKAGE - NAMESPACE - USER -} - -union GlobalObject = User | Namespace - -type RegistryInfo { - """Base URL for this registry""" - baseUrl: String! - - """Base URL for the default frontend""" - defaultFrontend: String! - - """URL to the graphql endpoint""" - graphqlUrl: String! - - """URL to the graphql endpoint""" - createBlogpostUrl: String - - """Public metadata about packages""" - packages: PackageInfo! - - """Public metadata about the graphql schema""" - schema: SchemaInfo! -} - -type PackageInfo { - """Number of package versions published this month""" - versionsPublishedThisMonth: Int! - - """Number of new packages published this month""" - newPackagesThisMonth: Int! - - """Number of package downloads this month""" - packageDownloadsThisMonth: Int! -} - -type SchemaInfo { - """Download link for graphql schema""" - downloadUrl: String! - - """SHA256 hash of the schema data""" - SHA256Hash: String! - - """Timestamp when the schema was last updated""" - lastUpdated: DateTime! -} - -type Mutation { - """Viewer accepts the latest ToS.""" - acceptTOS(input: AcceptTOSInput!): AcceptTOSPayload - publishDeployApp(input: PublishDeployAppInput!): PublishDeployAppPayload - deleteApp(input: DeleteAppInput!): DeleteAppPayload - - """Add current user to the waitlist.""" - joinWaitlist(input: JoinWaitlistInput!): JoinWaitlistPayload - - """Add stripe payment to the user""" - addPayment(input: AddPaymentInput!): AddPaymentPayload - - """ - Mutation to change the active version of a DeployApp to another DeployAppVersion. - """ - markAppVersionAsActive(input: MarkAppVersionAsActiveInput!): MarkAppVersionAsActivePayload - - """Set a payment method as default for the user.""" - makePaymentDefault(input: SetDefaultPaymentMethodInput!): SetDefaultPaymentMethodPayload - - """ - Try to detach a payment method from customer. - Fails if trying to detach a default method, - or if it's the only payment method. - """ - detachPaymentMethod(input: DetachPaymentMethodInput!): DetachPaymentMethodPayload - generateDeployConfigToken(input: GenerateDeployConfigTokenInput!): GenerateDeployConfigTokenPayload - renameApp(input: RenameAppInput!): RenameAppPayload - renameAppAlias(input: RenameAppAliasInput!): RenameAppAliasPayload - requestAppTransfer(input: RequestAppTransferInput!): RequestAppTransferPayload - acceptAppTransferRequest(input: AcceptAppTransferRequestInput!): AcceptAppTransferRequestPayload - removeAppTransferRequest(input: RemoveAppTransferRequestInput!): RemoveAppTransferRequestPayload - createRepoForAppTemplate(input: CreateRepoForAppTemplateInput!): CreateRepoForAppTemplatePayload - registerDomain(input: RegisterDomainInput!): RegisterDomainPayload - upsertDNSRecord(input: UpsertDNSRecordInput!): UpsertDNSRecordPayload - deleteDNSRecord(input: DeleteDNSRecordInput!): DeleteDNSRecordPayload - upsertDomainFromZoneFile(input: UpsertDomainFromZoneFileInput!): UpsertDomainFromZoneFilePayload - deleteDomain(input: DeleteDomainInput!): DeleteDomainPayload - tokenAuth(input: ObtainJSONWebTokenInput!): ObtainJSONWebTokenPayload - generateDeployToken(input: GenerateDeployTokenInput!): GenerateDeployTokenPayload - verifyAccessToken(token: String): Verify - refreshAccessToken(refreshToken: String): Refresh - revokeAccessToken(refreshToken: String): Revoke - registerUser(input: RegisterUserInput!): RegisterUserPayload - socialAuth(input: SocialAuthJWTInput!): SocialAuthJWTPayload - validateUserEmail(input: ValidateUserEmailInput!): ValidateUserEmailPayload - requestPasswordReset(input: RequestPasswordResetInput!): RequestPasswordResetPayload - requestValidationEmail(input: RequestValidationEmailInput!): RequestValidationEmailPayload - changeUserPassword(input: ChangeUserPasswordInput!): ChangeUserPasswordPayload - changeUserUsername(input: ChangeUserUsernameInput!): ChangeUserUsernamePayload - changeUserEmail(input: ChangeUserEmailInput!): ChangeUserEmailPayload - updateUserInfo(input: UpdateUserInfoInput!): UpdateUserInfoPayload - validateUserPassword(input: ValidateUserPasswordInput!): ValidateUserPasswordPayload - generateApiToken(input: GenerateAPITokenInput!): GenerateAPITokenPayload - revokeApiToken(input: RevokeAPITokenInput!): RevokeAPITokenPayload - checkUserExists(input: CheckUserExistsInput!): CheckUserExistsPayload - readNotification(input: ReadNotificationInput!): ReadNotificationPayload - seePendingNotifications(input: SeePendingNotificationsInput!): SeePendingNotificationsPayload - newNonce(input: NewNonceInput!): NewNoncePayload - validateNonce(input: ValidateNonceInput!): ValidateNoncePayload - mfa2totpGetToken(input: MFATOTPGetTokenInput!): MFATOTPTokenType - mfa2totpVerify(input: MFATOTPVerifyInput!): MFATOTPVerifyPayload - mfa2totpAuth(input: MFATOTPAuthInput!): MFAAuthResponse - mfa2RecoveryGetToken(input: MFAGenerateRecoveryTokenInput!): MFARecoveryCodes - mfa2RecoveryAuth(input: MFARecoveryAuthInput!): MFAAuthResponse - mfa2EmailAuth(input: MFAEmailAuthInput!): MFAAuthResponse - mfa2EmailGetToken(input: MFAGenerateEmailOTPInput!): MFAEmailGenerationResponse - publishPublicKey(input: PublishPublicKeyInput!): PublishPublicKeyPayload - publishPackage(input: PublishPackageInput!): PublishPackagePayload - updatePackage(input: UpdatePackageInput!): UpdatePackagePayload - likePackage(input: LikePackageInput!): LikePackagePayload - unlikePackage(input: UnlikePackageInput!): UnlikePackagePayload - watchPackage(input: WatchPackageInput!): WatchPackagePayload - unwatchPackage(input: UnwatchPackageInput!): UnwatchPackagePayload - archivePackage(input: ArchivePackageInput!): ArchivePackagePayload - renamePackage(input: RenamePackageInput!): RenamePackagePayload - changePackageVersionArchivedStatus(input: ChangePackageVersionArchivedStatusInput!): ChangePackageVersionArchivedStatusPayload - createNamespace(input: CreateNamespaceInput!): CreateNamespacePayload - updateNamespace(input: UpdateNamespaceInput!): UpdateNamespacePayload - deleteNamespace(input: DeleteNamespaceInput!): DeleteNamespacePayload - inviteNamespaceCollaborator(input: InviteNamespaceCollaboratorInput!): InviteNamespaceCollaboratorPayload - acceptNamespaceCollaboratorInvite(input: AcceptNamespaceCollaboratorInviteInput!): AcceptNamespaceCollaboratorInvitePayload - removeNamespaceCollaboratorInvite(input: RemoveNamespaceCollaboratorInviteInput!): RemoveNamespaceCollaboratorInvitePayload - removeNamespaceCollaborator(input: RemoveNamespaceCollaboratorInput!): RemoveNamespaceCollaboratorPayload - updateNamespaceCollaboratorRole(input: UpdateNamespaceCollaboratorRoleInput!): UpdateNamespaceCollaboratorRolePayload - updateNamespaceCollaboratorInviteRole(input: UpdateNamespaceCollaboratorInviteRoleInput!): UpdateNamespaceCollaboratorInviteRolePayload - invitePackageCollaborator(input: InvitePackageCollaboratorInput!): InvitePackageCollaboratorPayload - acceptPackageCollaboratorInvite(input: AcceptPackageCollaboratorInviteInput!): AcceptPackageCollaboratorInvitePayload - removePackageCollaboratorInvite(input: RemovePackageCollaboratorInviteInput!): RemovePackageCollaboratorInvitePayload - updatePackageCollaboratorRole(input: UpdatePackageCollaboratorRoleInput!): UpdatePackageCollaboratorRolePayload - updatePackageCollaboratorInviteRole(input: UpdatePackageCollaboratorInviteRoleInput!): UpdatePackageCollaboratorInviteRolePayload - removePackageCollaborator(input: RemovePackageCollaboratorInput!): RemovePackageCollaboratorPayload - requestPackageTransfer(input: RequestPackageTransferInput!): RequestPackageTransferPayload - acceptPackageTransferRequest(input: AcceptPackageTransferRequestInput!): AcceptPackageTransferRequestPayload - removePackageTransferRequest(input: RemovePackageTransferRequestInput!): RemovePackageTransferRequestPayload - generateBindingsForAllPackages(input: GenerateBindingsForAllPackagesInput!): GenerateBindingsForAllPackagesPayload - makePackagePublic(input: MakePackagePublicInput!): MakePackagePublicPayload -} - -"""Viewer accepts the latest ToS.""" -type AcceptTOSPayload { - TOS: TermsOfService! - clientMutationId: String -} - -input AcceptTOSInput { - clientMutationId: String -} - -type PublishDeployAppPayload { - deployAppVersion: DeployAppVersion! - clientMutationId: String -} - -input PublishDeployAppInput { - """The configuration of the app.""" - config: Configuration! - - """The name of the app.""" - name: ID - - """The owner of the app.""" - owner: ID - - """The description of the app.""" - description: String - - """If true, the new version will be set as the default version.""" - makeDefault: Boolean = true - - """ - If true, Publishing will fail if the source package does not have a valid webc. - """ - strict: Boolean = false - clientMutationId: String -} - -input Configuration { - deployment: AppConfigV1 - yamlConfig: String -} - -input AppConfigV1 { - kind: String = "wasmer.io/App.v0" - appId: ID - name: String! - description: String - package: String! -} - -type DeleteAppPayload { - success: Boolean! - clientMutationId: String -} - -input DeleteAppInput { - """App ID to delete.""" - id: ID! - clientMutationId: String -} - -"""Add current user to the waitlist.""" -type JoinWaitlistPayload { - waitlistMember: WaitlistMember! - clientMutationId: String -} - -input JoinWaitlistInput { - name: String! - clientMutationId: String -} - -"""Add stripe payment to the user""" -type AddPaymentPayload { - customerSecret: String! - clientMutationId: String -} - -input AddPaymentInput { - clientMutationId: String -} - -""" -Mutation to change the active version of a DeployApp to another DeployAppVersion. -""" -type MarkAppVersionAsActivePayload { - app: DeployApp! - clientMutationId: String -} - -input MarkAppVersionAsActiveInput { - """The ID of the DeployAppVersion to set as the new active version.""" - appVersion: ID! - clientMutationId: String -} - -"""Set a payment method as default for the user.""" -type SetDefaultPaymentMethodPayload { - success: Boolean! - billing: Billing! - clientMutationId: String -} - -input SetDefaultPaymentMethodInput { - paymentMethod: ID! - clientMutationId: String -} - -""" -Try to detach a payment method from customer. -Fails if trying to detach a default method, -or if it's the only payment method. -""" -type DetachPaymentMethodPayload { - success: Boolean! - billing: Billing! - clientMutationId: String -} - -input DetachPaymentMethodInput { - paymentMethod: ID! - clientMutationId: String -} - -type GenerateDeployConfigTokenPayload { - token: String! - config: String! - clientMutationId: String -} - -input GenerateDeployConfigTokenInput { - config: String! - clientMutationId: String -} - -type RenameAppPayload { - success: Boolean! - app: DeployApp! - clientMutationId: String -} - -input RenameAppInput { - """App ID to delete.""" - id: ID! - - """New name for the app.""" - name: String! - clientMutationId: String -} - -type RenameAppAliasPayload { - success: Boolean! - alias: AppAlias! - clientMutationId: String -} - -input RenameAppAliasInput { - """App alias ID to delete.""" - id: ID! - - """New name for the alias.""" - name: String! - clientMutationId: String -} - -type RequestAppTransferPayload { - appTransferRequest: AppTransferRequest - wasInstantlyTransferred: Boolean! - clientMutationId: String -} - -type AppTransferRequest implements Node { - """The ID of the object""" - id: ID! - requestedBy: User! - previousOwnerObjectId: Int! - newOwnerObjectId: Int! - app: DeployApp! - approvedBy: User - declinedBy: User - createdAt: DateTime! - expiresAt: DateTime! - closedAt: DateTime - previousOwner: Owner! - newOwner: Owner! -} - -input RequestAppTransferInput { - appId: ID! - newOwnerId: ID! - clientMutationId: String -} - -type AcceptAppTransferRequestPayload { - app: DeployApp! - appTransferRequest: AppTransferRequest! - clientMutationId: String -} - -input AcceptAppTransferRequestInput { - appTransferRequestId: ID! - clientMutationId: String -} - -type RemoveAppTransferRequestPayload { - app: DeployApp! - clientMutationId: String -} - -input RemoveAppTransferRequestInput { - appTransferRequestId: ID! - clientMutationId: String -} - -type CreateRepoForAppTemplatePayload { - success: Boolean! - repoId: ID! - clientMutationId: String -} - -input CreateRepoForAppTemplateInput { - templateId: ID! - name: String! - namespace: String! - private: Boolean = false - clientMutationId: String -} - -type RegisterDomainPayload { - success: Boolean! - domain: DNSDomain - clientMutationId: String -} - -input RegisterDomainInput { - name: String! - namespace: String - importRecords: Boolean = true - clientMutationId: String -} - -type UpsertDNSRecordPayload { - success: Boolean! - record: DNSRecord! - clientMutationId: String -} - -input UpsertDNSRecordInput { - kind: RecordKind! - domainId: String! - name: String! - value: String! - ttl: Int - recordId: String - mx: DNSMXExtraInput - clientMutationId: String -} - -enum RecordKind { - A - AAAA - CNAME - MX - NS - TXT - DNAME - PTR - SOA - SRV - CAA - SSHFP -} - -input DNSMXExtraInput { - preference: Int! -} - -type DeleteDNSRecordPayload { - success: Boolean! - clientMutationId: String -} - -input DeleteDNSRecordInput { - recordId: ID! - clientMutationId: String -} - -type UpsertDomainFromZoneFilePayload { - success: Boolean! - domain: DNSDomain! - clientMutationId: String -} - -input UpsertDomainFromZoneFileInput { - zoneFile: String! - deleteMissingRecords: Boolean - clientMutationId: String -} - -type DeleteDomainPayload { - success: Boolean! - clientMutationId: String -} - -input DeleteDomainInput { - domainId: ID! - clientMutationId: String -} - -type ObtainJSONWebTokenPayload { - payload: GenericScalar! - refreshExpiresIn: Int! - username: CaseInsensitiveString! - clientMutationId: String - token: String! - refreshToken: String! -} - -""" -The `GenericScalar` scalar type represents a generic -GraphQL scalar value that could be: -String, Boolean, Int, Float, List or Object. -""" -scalar GenericScalar - -""" -The `CaseInsensitiveString` scalar type represents textual data, represented as UTF-8 -character sequences. The String type is most often used by GraphQL to -represent free-form human-readable text. -""" -scalar CaseInsensitiveString - -input ObtainJSONWebTokenInput { - clientMutationId: String - username: String! - password: String! -} - -type GenerateDeployTokenPayload { - token: String! - deployConfigVersion: DeployAppVersion! - clientMutationId: String -} - -input GenerateDeployTokenInput { - deployConfigVersionId: String! - clientMutationId: String -} - -type Verify { - payload: GenericScalar! -} - -type Refresh { - payload: GenericScalar! - refreshExpiresIn: Int! - token: String! - refreshToken: String! -} - -type Revoke { - revoked: Int! -} - -type RegisterUserPayload { - token: String - clientMutationId: String -} - -input RegisterUserInput { - fullName: String! - email: String! - username: CaseInsensitiveString! - password: String! - acceptedTos: Boolean - clientMutationId: String -} - -type SocialAuthJWTPayload { - social: SocialAuth - token: String - clientMutationId: String -} - -input SocialAuthJWTInput { - provider: String! - accessToken: String! - register: Boolean = false - clientMutationId: String -} - -type ValidateUserEmailPayload { - user: User - clientMutationId: String -} - -input ValidateUserEmailInput { - """The user id""" - userId: ID - challenge: String! - clientMutationId: String -} - -type RequestPasswordResetPayload { - email: String! - errors: [ErrorType] - clientMutationId: String -} - -type ErrorType { - field: String! - messages: [String!]! -} - -input RequestPasswordResetInput { - email: String! - clientMutationId: String -} - -type RequestValidationEmailPayload { - user: User - success: Boolean! - clientMutationId: String -} - -input RequestValidationEmailInput { - """The user id""" - userId: ID - clientMutationId: String -} - -type ChangeUserPasswordPayload { - token: String - clientMutationId: String -} - -input ChangeUserPasswordInput { - """ - The token associated to change the password. If not existing it will use the request user by default - """ - token: String - oldPassword: String - password: String! - clientMutationId: String -} - -type ChangeUserUsernamePayload { - user: User - token: String - clientMutationId: String -} - -input ChangeUserUsernameInput { - """The new user username""" - username: CaseInsensitiveString! - clientMutationId: String -} - -type ChangeUserEmailPayload { - user: User! - clientMutationId: String -} - -input ChangeUserEmailInput { - newEmail: String! - clientMutationId: String -} - -type UpdateUserInfoPayload { - user: User - clientMutationId: String -} - -input UpdateUserInfoInput { - """The user id""" - userId: ID - - """The user full name""" - fullName: String - - """The user bio""" - bio: String - - """The user avatar""" - avatar: String - - """ - The user Twitter (it can be the url, or the handle with or without the @) - """ - twitter: String - - """ - The user Github (it can be the url, or the handle with or without the @) - """ - github: String - - """The user website (it must be a valid url)""" - websiteUrl: String - - """The user location""" - location: String - clientMutationId: String -} - -type ValidateUserPasswordPayload { - success: Boolean - clientMutationId: String -} - -input ValidateUserPasswordInput { - password: String! - clientMutationId: String -} - -type GenerateAPITokenPayload { - token: APIToken - tokenRaw: String - user: User - clientMutationId: String -} - -input GenerateAPITokenInput { - identifier: String - clientMutationId: String -} - -type RevokeAPITokenPayload { - token: APIToken - success: Boolean - clientMutationId: String -} - -input RevokeAPITokenInput { - """The API token ID""" - tokenId: ID! - clientMutationId: String -} - -type CheckUserExistsPayload { - exists: Boolean! - - """The user is only returned if the user input was the username""" - user: User - clientMutationId: String -} - -input CheckUserExistsInput { - """The user""" - user: String! - clientMutationId: String -} - -type ReadNotificationPayload { - notification: UserNotification - clientMutationId: String -} - -input ReadNotificationInput { - notificationId: ID! - clientMutationId: String -} - -type SeePendingNotificationsPayload { - success: Boolean - clientMutationId: String -} - -input SeePendingNotificationsInput { - clientMutationId: String -} - -type NewNoncePayload { - nonce: Nonce! - clientMutationId: String -} - -input NewNonceInput { - name: String! - callbackUrl: String! - clientMutationId: String -} - -type ValidateNoncePayload { - nonce: Nonce! - clientMutationId: String -} - -input ValidateNonceInput { - id: ID! - secret: String! - clientMutationId: String -} - -type MFATOTPTokenType { - qr: String - secretKey: String -} - -input MFATOTPGetTokenInput { - clientMutationId: String -} - -type MFATOTPVerifyPayload { - status: MFATOTPVerifyStatus - clientMutationId: String -} - -enum MFATOTPVerifyStatus { - SUCCESS - RECOVERY -} - -input MFATOTPVerifyInput { - answer: String! - secretKey: String! - clientMutationId: String -} - -"""Response object for MFAAuth mutation.""" -type MFAAuthResponse { - success: Boolean! - token: String - refreshToken: String - username: String - refreshTokenExpiresIn: Int -} - -input MFATOTPAuthInput { - username: String! - otp: String! - clientMutationId: String -} - -type MFARecoveryCodes { - codes: [String]! -} - -input MFAGenerateRecoveryTokenInput { - clientMutationId: String -} - -input MFARecoveryAuthInput { - username: String! - otp: String! - clientMutationId: String -} - -input MFAEmailAuthInput { - username: String! - otp: String! - clientMutationId: String -} - -type MFAEmailGenerationResponse { - success: Boolean! -} - -input MFAGenerateEmailOTPInput { - clientMutationId: String -} - -type PublishPublicKeyPayload { - success: Boolean! - publicKey: PublicKey! - clientMutationId: String -} - -input PublishPublicKeyInput { - keyId: String! - key: String! - verifyingSignatureId: String - clientMutationId: String -} - -type PublishPackagePayload { - success: Boolean! - packageVersion: PackageVersion - packageWebc: PackageWebc - clientMutationId: String -} - -input PublishPackageInput { - manifest: String! - name: String - namespace: String - version: String - description: String - license: String - licenseFile: String - readme: String - repository: String - homepage: String - file: String - signedUrl: String - signature: InputSignature - - """The package icon""" - icon: String - - """Whether the package is private""" - private: Boolean = false - - """The upload format of the package""" - uploadFormat: UploadFormat = targz - - """Whether to wait for webc generation to finish""" - wait: Boolean = false - clientMutationId: String -} - -input InputSignature { - publicKeyKeyId: String! - data: String! -} - -enum UploadFormat { - targz - webcv2 - webcv3 -} - -type UpdatePackagePayload { - package: Package! - clientMutationId: String -} - -input UpdatePackageInput { - packageId: ID! - - """The package icon""" - icon: String - clientMutationId: String -} - -type LikePackagePayload { - package: Package! - clientMutationId: String -} - -input LikePackageInput { - packageId: ID! - clientMutationId: String -} - -type UnlikePackagePayload { - package: Package! - clientMutationId: String -} - -input UnlikePackageInput { - packageId: ID! - clientMutationId: String -} - -type WatchPackagePayload { - package: Package! - clientMutationId: String -} - -input WatchPackageInput { - packageId: ID! - clientMutationId: String -} - -type UnwatchPackagePayload { - package: Package! - clientMutationId: String -} - -input UnwatchPackageInput { - packageId: ID! - clientMutationId: String -} - -type ArchivePackagePayload { - package: Package! - clientMutationId: String -} - -input ArchivePackageInput { - packageId: ID! - clientMutationId: String -} - -type RenamePackagePayload { - package: Package! - clientMutationId: String -} - -input RenamePackageInput { - packageId: ID! - newName: String! - clientMutationId: String -} - -type ChangePackageVersionArchivedStatusPayload { - packageVersion: PackageVersion! - clientMutationId: String -} - -input ChangePackageVersionArchivedStatusInput { - packageVersionId: ID! - isArchived: Boolean - clientMutationId: String -} - -type CreateNamespacePayload { - namespace: Namespace! - user: User! - clientMutationId: String -} - -input CreateNamespaceInput { - name: String! - - """The namespace display name""" - displayName: String - - """The namespace description""" - description: String - - """The namespace avatar""" - avatar: String - clientMutationId: String -} - -type UpdateNamespacePayload { - namespace: Namespace! - clientMutationId: String -} - -input UpdateNamespaceInput { - namespaceId: ID! - - """The namespace slug name""" - name: String - - """The namespace display name""" - displayName: String - - """The namespace description""" - description: String - - """The namespace avatar""" - avatar: String - - """ - The user Twitter (it can be the url, or the handle with or without the @) - """ - twitter: String - - """ - The user Github (it can be the url, or the handle with or without the @) - """ - github: String - - """The user website (it must be a valid url)""" - websiteUrl: String - clientMutationId: String -} - -type DeleteNamespacePayload { - success: Boolean! - clientMutationId: String -} - -input DeleteNamespaceInput { - namespaceId: ID! - clientMutationId: String -} - -type InviteNamespaceCollaboratorPayload { - invite: NamespaceCollaboratorInvite! - namespace: Namespace! - clientMutationId: String -} - -input InviteNamespaceCollaboratorInput { - namespaceId: ID! - role: GrapheneRole! - username: String - email: String - clientMutationId: String -} - -type AcceptNamespaceCollaboratorInvitePayload { - namespaceCollaboratorInvite: NamespaceCollaboratorInvite! - clientMutationId: String -} - -input AcceptNamespaceCollaboratorInviteInput { - inviteId: ID! - clientMutationId: String -} - -type RemoveNamespaceCollaboratorInvitePayload { - namespace: Namespace! - clientMutationId: String -} - -input RemoveNamespaceCollaboratorInviteInput { - inviteId: ID! - clientMutationId: String -} - -type RemoveNamespaceCollaboratorPayload { - namespace: Namespace! - clientMutationId: String -} - -input RemoveNamespaceCollaboratorInput { - namespaceCollaboratorId: ID! - clientMutationId: String -} - -type UpdateNamespaceCollaboratorRolePayload { - collaborator: NamespaceCollaborator! - clientMutationId: String -} - -input UpdateNamespaceCollaboratorRoleInput { - namespaceCollaboratorId: ID! - role: GrapheneRole! - clientMutationId: String -} - -type UpdateNamespaceCollaboratorInviteRolePayload { - collaboratorInvite: NamespaceCollaboratorInvite! - clientMutationId: String -} - -input UpdateNamespaceCollaboratorInviteRoleInput { - namespaceCollaboratorInviteId: ID! - role: GrapheneRole! - clientMutationId: String -} - -type InvitePackageCollaboratorPayload { - invite: PackageCollaboratorInvite! - package: Package! - clientMutationId: String -} - -input InvitePackageCollaboratorInput { - packageName: String! - role: GrapheneRole! - username: String - email: String - clientMutationId: String -} - -type AcceptPackageCollaboratorInvitePayload { - packageCollaboratorInvite: PackageCollaboratorInvite! - clientMutationId: String -} - -input AcceptPackageCollaboratorInviteInput { - inviteId: ID! - clientMutationId: String -} - -type RemovePackageCollaboratorInvitePayload { - package: Package! - clientMutationId: String -} - -input RemovePackageCollaboratorInviteInput { - inviteId: ID! - clientMutationId: String -} - -type UpdatePackageCollaboratorRolePayload { - collaborator: PackageCollaborator! - clientMutationId: String -} - -input UpdatePackageCollaboratorRoleInput { - packageCollaboratorId: ID! - role: GrapheneRole! - clientMutationId: String -} - -type UpdatePackageCollaboratorInviteRolePayload { - collaboratorInvite: PackageCollaboratorInvite! - clientMutationId: String -} - -input UpdatePackageCollaboratorInviteRoleInput { - packageCollaboratorInviteId: ID! - role: GrapheneRole! - clientMutationId: String -} - -type RemovePackageCollaboratorPayload { - package: Package! - clientMutationId: String -} - -input RemovePackageCollaboratorInput { - packageCollaboratorId: ID! - clientMutationId: String -} - -type RequestPackageTransferPayload { - package: Package! - wasInstantlyTransferred: Boolean! - packageTransferRequest: PackageTransferRequest - clientMutationId: String -} - -input RequestPackageTransferInput { - packageId: ID! - newOwnerId: ID! - clientMutationId: String -} - -type AcceptPackageTransferRequestPayload { - package: Package! - packageTransferRequest: PackageTransferRequest! - clientMutationId: String -} - -input AcceptPackageTransferRequestInput { - packageTransferRequestId: ID! - clientMutationId: String -} - -type RemovePackageTransferRequestPayload { - package: Package! - clientMutationId: String -} - -input RemovePackageTransferRequestInput { - packageTransferRequestId: ID! - clientMutationId: String -} - -type GenerateBindingsForAllPackagesPayload { - message: String! - clientMutationId: String -} - -input GenerateBindingsForAllPackagesInput { - bindingsGeneratorId: ID - bindingsGeneratorCommand: String - clientMutationId: String -} - -type MakePackagePublicPayload { - package: Package! - clientMutationId: String -} - -input MakePackagePublicInput { - """The ID of the package to make public""" - id: ID! - clientMutationId: String -} - -type Subscription { - streamLogs( - appVersionId: ID! - - """ - Get logs starting from this timestamp. Takes ISO timestamp in UTC timezone. - """ - startingFromISO: DateTime - - """ - Fetch logs until this timestamp. Takes ISO timestamp in UTC timezone. If specified, the subscription will at this time. - """ - untilISO: DateTime - - """Filter logs by stream""" - streams: [LogStream] - - """Filter logs by instance ids""" - instanceIds: [String] - - """Search logs for this term""" - searchTerm: String - ): Log! - waitOnRepoCreation(repoId: ID!): Boolean! - appIsPublishedFromRepo(repoId: ID!): DeployAppVersion! - packageVersionCreated(publishedBy: ID, ownerId: ID): PackageVersion! - - """Subscribe to package version ready""" - packageVersionReady(packageVersionId: ID!): PackageVersionReadyResponse! - userNotificationCreated(userId: ID!): UserNotificationCreated! -} - -type PackageVersionReadyResponse { - state: PackageVersionState! - packageVersion: PackageVersion! - success: Boolean! -} - -enum PackageVersionState { - WEBC_GENERATED - BINDINGS_GENERATED - NATIVE_EXES_GENERATED -} - -type UserNotificationCreated { - notification: UserNotification - notificationDeletedId: ID -} diff --git a/lib/registry/graphql/subscriptions/packageVersionReady.graphql b/lib/registry/graphql/subscriptions/packageVersionReady.graphql deleted file mode 100644 index f7324e50daf..00000000000 --- a/lib/registry/graphql/subscriptions/packageVersionReady.graphql +++ /dev/null @@ -1,6 +0,0 @@ -subscription PackageVersionReady ($packageVersionId: ID!) { - packageVersionReady(packageVersionId: $packageVersionId) { - state - success - } -} diff --git a/lib/registry/src/api.rs b/lib/registry/src/api.rs deleted file mode 100644 index 7684f148eff..00000000000 --- a/lib/registry/src/api.rs +++ /dev/null @@ -1,27 +0,0 @@ -use anyhow::Context; - -use crate::RegistryClient; - -use crate::graphql::mutations::{self}; -use crate::types::NewNonceOutput; - -/// Generate a new Nonce -/// -/// Takes a name and a callbackUrl and returns a nonce -pub async fn create_nonce( - client: &RegistryClient, - name: String, - callback_url: String, -) -> Result { - let vars = mutations::new_nonce::Variables { name, callback_url }; - let nonce = client - .execute::(vars) - .await? - .new_nonce - .context("Query did not return a nonce")? - .nonce; - - Ok(NewNonceOutput { - auth_url: nonce.auth_url, - }) -} diff --git a/lib/registry/src/client.rs b/lib/registry/src/client.rs deleted file mode 100644 index 3ae909bc4b1..00000000000 --- a/lib/registry/src/client.rs +++ /dev/null @@ -1,100 +0,0 @@ -use anyhow::Context; -use graphql_client::GraphQLQuery; -use url::Url; - -/// API client for the Wasmer registry. -#[derive(Clone)] -pub struct RegistryClient { - client: reqwest::Client, - endpoint: Url, - token: Option, -} - -impl RegistryClient { - /// Construct a new registry. - pub fn new(endpoint: Url, token: Option, user_agent: Option) -> Self { - let user_agent = user_agent.unwrap_or_else(Self::default_user_agent); - let client = reqwest::Client::builder() - .user_agent(user_agent) - .build() - .unwrap(); - Self { - client, - endpoint, - token, - } - } - - /// Construct a client from a [`crate::config::RegistryLogin`]. - pub fn from_registry(registry: crate::config::RegistryLogin) -> Result { - let endpoint = registry.registry.parse().context("Invalid registry URL")?; - let client = Self::new(endpoint, Some(registry.token), None); - Ok(client) - } - - pub(crate) fn default_user_agent() -> String { - format!( - "wasmer/{} {} {}", - env!("CARGO_PKG_VERSION"), - whoami::platform(), - crate::graphql::whoami_distro(), - ) - } - - /// Set the GraphQL API endpoint. - pub fn with_endpoint(self, endpoint: Url) -> Self { - Self { endpoint, ..self } - } - - /// Set the authentication token. - pub fn with_token(self, token: String) -> Self { - Self { - token: Some(token), - ..self - } - } - - /// Execute a GraphQL query. - pub(crate) async fn execute_unchecked( - &self, - vars: Q::Variables, - ) -> Result, reqwest::Error> { - let body = Q::build_query(vars); - - let req = self.client.post(self.endpoint.as_str()); - - let req = if let Some(token) = &self.token { - req.bearer_auth(token) - } else { - req - }; - req.json(&body) - .send() - .await? - .error_for_status()? - .json::>() - .await - } - - /// Execute a GraphQL query, and convert a response with errors to a Rust error. - pub(crate) async fn execute( - &self, - vars: Q::Variables, - ) -> Result { - let res = self.execute_unchecked::(vars).await?; - - match (res.data, res.errors) { - (_, Some(errors)) => { - // TODO: Better error forwaring with a custom error type. - let errors = errors - .iter() - .map(|x| x.to_string()) - .collect::>() - .join(", "); - anyhow::bail!("GraphQL error: {errors}"); - } - (Some(data), None) => Ok(data), - (None, None) => anyhow::bail!("GraphQL response contained no data"), - } - } -} diff --git a/lib/registry/src/config.rs b/lib/registry/src/config.rs deleted file mode 100644 index 4eb49b5bb2b..00000000000 --- a/lib/registry/src/config.rs +++ /dev/null @@ -1,323 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::path::{Path, PathBuf}; -use url::Url; - -pub static GLOBAL_CONFIG_DATABASE_FILE_NAME: &str = "wasmer.sqlite"; - -#[derive(Deserialize, Default, Serialize, Debug, PartialEq, Eq)] -pub struct WasmerConfig { - /// Whether or not telemetry is enabled. - #[serde(default)] - pub telemetry_enabled: bool, - - /// Whether or not updated notifications are enabled. - #[serde(default)] - pub update_notifications_enabled: bool, - - /// The registry that wasmer will connect to. - pub registry: MultiRegistry, - - /// The proxy to use when connecting to the Internet. - #[serde(default)] - pub proxy: Proxy, -} - -pub const fn wax_default_cooldown() -> i32 { - 5 * 60 -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Default)] -pub struct Proxy { - pub url: Option, -} - -/// Struct to store login tokens for multiple registry URLs -/// inside of the wasmer.toml configuration file -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] -pub struct MultiRegistry { - /// Currently active registry - pub active_registry: String, - /// Map from "RegistryUrl" to "LoginToken", in order to - /// be able to be able to easily switch between registries - pub tokens: Vec, -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] -pub struct RegistryLogin { - /// Registry URL to login to - pub registry: String, - /// Login token for the registry - pub token: String, -} - -impl Default for MultiRegistry { - fn default() -> Self { - MultiRegistry { - active_registry: format_graphql("wasmer.io"), - tokens: Vec::new(), - } - } -} - -#[derive(Deserialize, Serialize, Debug, PartialEq, Eq, Clone)] -pub struct Registry { - pub url: String, - pub token: Option, -} - -pub fn format_graphql(registry: &str) -> String { - if let Ok(mut url) = Url::parse(registry) { - // Looks like we've got a valid URL. Let's try to use it as-is. - if url.has_host() { - if url.path() == "/" { - // make sure we convert http://registry.wasmer.io/ to - // http://registry.wasmer.io/graphql - url.set_path("/graphql"); - } - - return url.to_string(); - } - } - - if !registry.contains("://") && !registry.contains('/') { - return endpoint_from_domain_name(registry); - } - - // looks like we've received something we can't deal with. Just pass it - // through as-is and hopefully it'll either work or the end user can figure - // it out - registry.to_string() -} - -/// By convention, something like `"wasmer.io"` should be converted to -/// `"https://registry.wasmer.io/graphql"`. -fn endpoint_from_domain_name(domain_name: &str) -> String { - if domain_name.contains("localhost") { - return format!("http://{domain_name}/graphql"); - } - - format!("https://registry.{domain_name}/graphql") -} - -fn test_if_registry_present(registry: &str) -> Result<(), String> { - crate::utils::get_username_registry_token(registry, "") - .map(|_| ()) - .map_err(|e| format!("{e}")) -} - -#[derive(PartialEq, Eq, Copy, Clone)] -pub enum UpdateRegistry { - Update, - LeaveAsIs, -} - -impl MultiRegistry { - /// Gets the current (active) registry URL - pub fn clear_current_registry_token(&mut self) { - let MultiRegistry { - active_registry, - tokens, - } = self; - tokens.retain(|i| i.registry != *active_registry); - tokens.retain(|i| i.registry != format_graphql(active_registry)); - } - - pub fn get_graphql_url(&self) -> String { - let registry = self.get_current_registry(); - format_graphql(®istry) - } - - /// Gets the current (active) registry URL - pub fn get_current_registry(&self) -> String { - format_graphql(&self.active_registry) - } - - pub fn current_login(&self) -> Option<&RegistryLogin> { - self.tokens - .iter() - .find(|login| login.registry == self.active_registry) - } - - /// Sets the current (active) registry URL - pub fn set_current_registry(&mut self, registry: &str) { - let registry = format_graphql(registry); - if let Err(e) = test_if_registry_present(®istry) { - println!("Error when trying to ping registry {registry:?}: {e}"); - println!("WARNING: Registry {registry:?} will be used, but commands may not succeed."); - } - self.active_registry = registry; - } - - /// Returns the login token for the registry - pub fn get_login_token_for_registry(&self, registry: &str) -> Option { - let registry_formatted = format_graphql(registry); - self.tokens - .iter() - .filter(|login| login.registry == registry || login.registry == registry_formatted) - .last() - .map(|login| login.token.clone()) - } - - /// Sets the login token for the registry URL - pub fn set_login_token_for_registry( - &mut self, - registry: &str, - token: &str, - update_current_registry: UpdateRegistry, - ) { - let registry_formatted = format_graphql(registry); - self.tokens - .retain(|login| !(login.registry == registry || login.registry == registry_formatted)); - self.tokens.push(RegistryLogin { - registry: format_graphql(registry), - token: token.to_string(), - }); - if update_current_registry == UpdateRegistry::Update { - self.active_registry = format_graphql(registry); - } - } -} - -impl WasmerConfig { - pub(crate) const ENV_VAR_WASMER_REGISTRY_TOKEN: &'static str = "WASMER_TOKEN"; - pub(crate) const ENV_VAR_WASMER_REGISTRY_TOKEN_LEGACY: &'static str = "WAPM_REGISTRY_TOKEN"; - - /// Save the config to a file - pub fn save>(&self, to: P) -> anyhow::Result<()> { - use std::{fs::File, io::Write}; - let config_serialized = toml::to_string(&self)?; - let mut file = File::create(to)?; - file.write_all(config_serialized.as_bytes())?; - Ok(()) - } - - pub fn from_file(wasmer_dir: &Path) -> Result { - let path = Self::get_file_location(wasmer_dir); - match std::fs::read_to_string(path) { - Ok(config_toml) => Ok(toml::from_str(&config_toml).unwrap_or_else(|_| Self::default())), - Err(_e) => Ok(Self::default()), - } - } - - /// Creates and returns the `WASMER_DIR` directory (or $HOME/.wasmer as a fallback) - pub fn get_wasmer_dir() -> Result { - Ok( - if let Some(folder_str) = std::env::var("WASMER_DIR").ok().filter(|s| !s.is_empty()) { - let folder = PathBuf::from(folder_str); - std::fs::create_dir_all(folder.clone()) - .map_err(|e| format!("cannot create config directory: {e}"))?; - folder - } else { - #[allow(unused_variables)] - let default_dir = Self::get_current_dir() - .ok() - .unwrap_or_else(|| PathBuf::from("/".to_string())); - let home_dir = - dirs::home_dir().ok_or_else(|| "cannot find home directory".to_string())?; - let mut folder = home_dir; - folder.push(".wasmer"); - std::fs::create_dir_all(folder.clone()) - .map_err(|e| format!("cannot create config directory: {e}"))?; - folder - }, - ) - } - - /// Load the config based on environment variables and default config file locations. - pub fn from_env() -> Result { - let dir = Self::get_wasmer_dir() - .map_err(|err| anyhow::anyhow!("Could not determine wasmer dir: {err}"))?; - let file_path = Self::get_file_location(&dir); - Self::from_file(&file_path).map_err(|err| { - anyhow::anyhow!( - "Could not load config file at '{}': {}", - file_path.display(), - err - ) - }) - } - - pub fn get_current_dir() -> std::io::Result { - std::env::current_dir() - } - - pub fn get_file_location(wasmer_dir: &Path) -> PathBuf { - wasmer_dir.join(crate::GLOBAL_CONFIG_FILE_NAME) - } - - pub fn get_database_file_path(wasmer_dir: &Path) -> PathBuf { - wasmer_dir.join(GLOBAL_CONFIG_DATABASE_FILE_NAME) - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn test_registries_switch_token() { - let mut registries = MultiRegistry::default(); - - registries.set_current_registry("https://registry.wasmer.wtf"); - assert_eq!( - registries.get_current_registry(), - "https://registry.wasmer.wtf/graphql".to_string() - ); - registries.set_login_token_for_registry( - "https://registry.wasmer.io", - "token1", - UpdateRegistry::LeaveAsIs, - ); - assert_eq!( - registries.get_current_registry(), - "https://registry.wasmer.wtf/graphql".to_string() - ); - assert_eq!( - registries.get_login_token_for_registry(®istries.get_current_registry()), - None - ); - registries.set_current_registry("https://registry.wasmer.io"); - assert_eq!( - registries.get_login_token_for_registry(®istries.get_current_registry()), - Some("token1".to_string()) - ); - registries.clear_current_registry_token(); - assert_eq!( - registries.get_login_token_for_registry(®istries.get_current_registry()), - None - ); - } - - #[test] - fn format_registry_urls() { - let inputs = [ - // Domain names work - ("wasmer.io", "https://registry.wasmer.io/graphql"), - ("wasmer.wtf", "https://registry.wasmer.wtf/graphql"), - // Plain URLs - ( - "https://registry.wasmer.wtf/graphql", - "https://registry.wasmer.wtf/graphql", - ), - ( - "https://registry.wasmer.wtf/something/else", - "https://registry.wasmer.wtf/something/else", - ), - // We don't automatically prepend the domain name with - // "registry", but we will make sure "/" gets turned into "/graphql" - ("https://wasmer.wtf/", "https://wasmer.wtf/graphql"), - ("https://wasmer.wtf", "https://wasmer.wtf/graphql"), - // local development - ( - "http://localhost:8000/graphql", - "http://localhost:8000/graphql", - ), - ("localhost:8000", "http://localhost:8000/graphql"), - ]; - - for (input, expected) in inputs { - let url = format_graphql(input); - assert_eq!(url, expected); - } - } -} diff --git a/lib/registry/src/graphql/mod.rs b/lib/registry/src/graphql/mod.rs deleted file mode 100644 index 467a1aaec84..00000000000 --- a/lib/registry/src/graphql/mod.rs +++ /dev/null @@ -1,157 +0,0 @@ -pub(crate) mod mutations; -pub(crate) mod proxy; -pub(crate) mod queries; -pub(crate) mod subscriptions; - -use graphql_client::*; -use reqwest::{ - blocking::{multipart::Form, Client}, - header::USER_AGENT, -}; -use std::env; -use std::time::Duration; - -use crate::config::WasmerConfig; - -pub fn whoami_distro() -> String { - #[cfg(target_os = "wasi")] - { - whoami::os().to_lowercase() - } - #[cfg(not(target_os = "wasi"))] - { - whoami::distro().to_lowercase() - } -} - -fn setup_client() -> Result { - let builder = Client::builder(); - let builder = proxy::maybe_set_up_proxy_blocking(builder)?; - builder.build().map_err(|e| e.into()) -} - -/// This function is being used to "ping" the registry -/// (see test_if_registry_present and see whether the response -/// is valid JSON, it doesn't check the response itself, -/// since the response format might change -pub fn execute_query_modifier_inner_check_json( - registry_url: &str, - login_token: &str, - query: &QueryBody, - timeout: Option, - form_modifier: F, -) -> anyhow::Result<()> -where - V: serde::Serialize, - F: FnOnce(Form) -> Form, -{ - let client = setup_client()?; - - let vars = serde_json::to_string(&query.variables).unwrap(); - - let form = Form::new() - .text("query", query.query.to_string()) - .text("operationName", query.operation_name.to_string()) - .text("variables", vars); - - let form = form_modifier(form); - - let user_agent = crate::client::RegistryClient::default_user_agent(); - - let mut res = client - .post(registry_url) - .multipart(form) - .bearer_auth( - env::var(WasmerConfig::ENV_VAR_WASMER_REGISTRY_TOKEN) - .ok() - .or_else(|| env::var(WasmerConfig::ENV_VAR_WASMER_REGISTRY_TOKEN_LEGACY).ok()) - .unwrap_or_else(|| login_token.to_string()), - ) - .header(USER_AGENT, user_agent); - - if let Some(t) = timeout { - res = res.timeout(t); - } - - let res = res.send()?; - - let _: Response = res.json()?; - - Ok(()) -} - -pub fn execute_query_modifier_inner( - registry_url: &str, - login_token: &str, - query: &QueryBody, - timeout: Option, - form_modifier: F, -) -> anyhow::Result -where - for<'de> R: serde::Deserialize<'de>, - V: serde::Serialize, - F: FnOnce(Form) -> Form, -{ - let client = setup_client()?; - - let vars = serde_json::to_string(&query.variables).unwrap(); - - let form = Form::new() - .text("query", query.query.to_string()) - .text("operationName", query.operation_name.to_string()) - .text("variables", vars); - - let form = form_modifier(form); - - let user_agent = crate::client::RegistryClient::default_user_agent(); - - let mut res = client - .post(registry_url) - .multipart(form) - .bearer_auth( - env::var("WASMER_TOKEN") - .ok() - .or_else(|| env::var("WAPM_REGISTRY_TOKEN").ok()) - .unwrap_or_else(|| login_token.to_string()), - ) - .header(USER_AGENT, user_agent); - - if let Some(t) = timeout { - res = res.timeout(t); - } - - let res = res.send()?; - let response_body: Response = res.json()?; - if let Some(errors) = response_body.errors { - let error_messages: Vec = errors.into_iter().map(|err| err.message).collect(); - return Err(anyhow::anyhow!("{}", error_messages.join(", "))); - } - response_body - .data - .ok_or_else(|| anyhow::anyhow!("missing response data")) -} - -pub fn execute_query( - registry_url: &str, - login_token: &str, - query: &QueryBody, -) -> anyhow::Result -where - for<'de> R: serde::Deserialize<'de>, - V: serde::Serialize, -{ - execute_query_modifier_inner(registry_url, login_token, query, None, |f| f) -} - -pub fn execute_query_with_timeout( - registry_url: &str, - login_token: &str, - timeout: Duration, - query: &QueryBody, -) -> anyhow::Result -where - for<'de> R: serde::Deserialize<'de>, - V: serde::Serialize, -{ - execute_query_modifier_inner(registry_url, login_token, query, Some(timeout), |f| f) -} diff --git a/lib/registry/src/graphql/mutations.rs b/lib/registry/src/graphql/mutations.rs deleted file mode 100644 index 18558379fff..00000000000 --- a/lib/registry/src/graphql/mutations.rs +++ /dev/null @@ -1,37 +0,0 @@ -use graphql_client::GraphQLQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/mutations/publish_package_chunked.graphql", - response_derives = "Debug", - variables_derives = "Debug" - // additional_derives = "Debug" -)] -pub(crate) struct PublishPackageMutationChunked; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/mutations/generate_deploy_token.graphql", - response_derives = "Debug" -)] -pub(crate) struct GenerateDeployToken; - -pub type JSONString = String; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/mutations/publish_deploy_app.graphql", - response_derives = "Debug" -)] -pub(crate) struct PublishDeployApp; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/mutations/new_nonce.graphql", - response_derives = "Debug" -)] -pub(crate) struct NewNonce; diff --git a/lib/registry/src/graphql/proxy.rs b/lib/registry/src/graphql/proxy.rs deleted file mode 100644 index 75ac81faec2..00000000000 --- a/lib/registry/src/graphql/proxy.rs +++ /dev/null @@ -1,73 +0,0 @@ -//! Code for dealing with setting things up to proxy network requests - -use std::env; - -use anyhow::Context; -use thiserror::Error; - -#[derive(Debug, Error)] -pub enum ProxyError { - #[error("Failed to parse URL from {}: {}", url_location, error_message)] - UrlParseError { - url_location: String, - error_message: String, - }, - - #[error("Could not connect to proxy: {0}")] - ConnectionError(String), -} - -pub fn maybe_set_up_proxy_blocking( - builder: reqwest::blocking::ClientBuilder, -) -> anyhow::Result { - if let Some(proxy) = - maybe_set_up_proxy_inner().context("failed to setup proxy for reqwest Client")? - { - return Ok(builder.proxy(proxy)); - } - Ok(builder) -} - -/// Tries to set up a proxy -/// -/// This function reads from wasmer config's `proxy.url` first, then checks -/// `ALL_PROXY`, `HTTPS_PROXY`, and `HTTP_PROXY` environment variables, in both -/// upper case and lower case, in that order. -/// -/// If a proxy is specified in wasmer config's `proxy.url`, it is assumed -/// to be a general proxy -/// -/// A return value of `Ok(None)` means that there was no attempt to set up a proxy, -/// `Ok(Some(proxy))` means that the proxy was set up successfully, and `Err(e)` that -/// there was a failure while attempting to set up the proxy. -fn maybe_set_up_proxy_inner() -> anyhow::Result> { - let proxy = if let Ok(proxy_url) = env::var("ALL_PROXY").or_else(|_| env::var("all_proxy")) { - reqwest::Proxy::all(&proxy_url).map(|proxy| (proxy_url, proxy, "ALL_PROXY")) - } else if let Ok(https_proxy_url) = env::var("HTTPS_PROXY").or_else(|_| env::var("https_proxy")) - { - reqwest::Proxy::https(&https_proxy_url).map(|proxy| (https_proxy_url, proxy, "HTTPS_PROXY")) - } else if let Ok(http_proxy_url) = env::var("HTTP_PROXY").or_else(|_| env::var("http_proxy")) { - reqwest::Proxy::http(&http_proxy_url).map(|proxy| (http_proxy_url, proxy, "http_proxy")) - } else { - return Ok(None); - } - .map_err(|e| ProxyError::ConnectionError(e.to_string())) - .and_then( - |(proxy_url_str, proxy, url_location): (String, _, &'static str)| { - url::Url::parse(&proxy_url_str) - .map_err(|e| ProxyError::UrlParseError { - url_location: url_location.to_string(), - error_message: e.to_string(), - }) - .map(|url| { - if !(url.username().is_empty()) && url.password().is_some() { - proxy.basic_auth(url.username(), url.password().unwrap_or_default()) - } else { - proxy - } - }) - }, - )?; - - Ok(Some(proxy)) -} diff --git a/lib/registry/src/graphql/queries.rs b/lib/registry/src/graphql/queries.rs deleted file mode 100644 index a95234f8551..00000000000 --- a/lib/registry/src/graphql/queries.rs +++ /dev/null @@ -1,75 +0,0 @@ -//! Low-level GraphQL queries used by this crate. -//! -//! If possible, users should prefer the high-level functions exposed under -//! [`crate`]. -//! -//! This module is primarily used in combination with -//! [`crate::graphql::execute_query()`] as an "escape hatch" for accessing -//! information that may not be exposed via the high-level functions. -//! -//! # Backwards Compatibility -//! -//! Queries won't be deleted or have breaking changes to their inputs during -//! patch releases, however new fields may be added to the response types -//! generated by `graphql_client` at any time. -//! -//! Users should treat all response types as if they had the `#[non_exhaustive]` -//! attribute. - -use graphql_client::GraphQLQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/get_package_version.graphql", - response_derives = "Debug" -)] -pub(crate) struct GetPackageVersionQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/get_package_by_command.graphql", - response_derives = "Debug" -)] -pub(crate) struct GetPackageByCommandQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/test_if_registry_present.graphql", - response_derives = "Debug" -)] -pub(crate) struct TestIfRegistryPresent; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/get_bindings.graphql", - response_derives = "Debug,Clone,PartialEq,Eq" -)] -pub(crate) struct GetBindingsQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/get_signed_url.graphql", - response_derives = "Debug, Clone" -)] -pub(crate) struct GetSignedUrl; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/get_interface_version.graphql", - response_derives = "Debug" -)] -pub(crate) struct GetInterfaceVersionQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/queries/whoami.graphql", - response_derives = "Debug" -)] -pub struct WhoAmIQuery; diff --git a/lib/registry/src/graphql/subscriptions.rs b/lib/registry/src/graphql/subscriptions.rs deleted file mode 100644 index 6f0115f4a02..00000000000 --- a/lib/registry/src/graphql/subscriptions.rs +++ /dev/null @@ -1,9 +0,0 @@ -use graphql_client::GraphQLQuery; - -#[derive(GraphQLQuery)] -#[graphql( - schema_path = "graphql/schema.graphql", - query_path = "graphql/subscriptions/packageVersionReady.graphql", - response_derives = "Debug" -)] -pub struct PackageVersionReady; diff --git a/lib/registry/src/interface.rs b/lib/registry/src/interface.rs deleted file mode 100644 index 614ae386dcd..00000000000 --- a/lib/registry/src/interface.rs +++ /dev/null @@ -1,44 +0,0 @@ -#![cfg_attr( - not(feature = "full"), - allow(dead_code, unused_imports, unused_variables) -)] - -use graphql_client::GraphQLQuery; - -use crate::graphql::{ - execute_query, - queries::{get_interface_version_query, GetInterfaceVersionQuery}, -}; - -#[derive(Debug)] -pub struct InterfaceFromServer { - pub name: String, - pub version: String, - pub content: String, -} - -impl InterfaceFromServer { - fn get_response( - registry: &str, - name: String, - version: String, - ) -> anyhow::Result { - let q = GetInterfaceVersionQuery::build_query(get_interface_version_query::Variables { - name, - version, - }); - execute_query(registry, "", &q) - } - - pub fn get(registry: &str, name: String, version: String) -> anyhow::Result { - let response = Self::get_response(registry, name, version)?; - let response_val = response - .interface - .ok_or_else(|| anyhow::anyhow!("Error downloading Interface from the server"))?; - Ok(Self { - name: response_val.interface.name, - version: response_val.version, - content: response_val.content, - }) - } -} diff --git a/lib/registry/src/lib.rs b/lib/registry/src/lib.rs deleted file mode 100644 index 3303ef97c0e..00000000000 --- a/lib/registry/src/lib.rs +++ /dev/null @@ -1,526 +0,0 @@ -//! High-level interactions with the Wasmer backend. -//! -//! The GraphQL schema can be updated by running `make` in the Wasmer repo's -//! root directory. -//! -//! ```console -//! $ make update-graphql-schema -//! curl -sSfL https://registry.wasmer.io/graphql/schema.graphql > lib/registry/graphql/schema.graphql -//! ``` -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] - -pub mod api; -mod client; -pub mod config; -pub mod graphql; -pub mod interface; -pub mod login; -pub mod package; -pub mod publish; -pub mod subscriptions; -pub mod types; -pub mod utils; -pub mod wasmer_env; - -pub use crate::client::RegistryClient; - -use std::{ - fmt, - path::{Path, PathBuf}, - time::Duration, -}; - -use anyhow::Context; -use graphql_client::GraphQLQuery; -use tar::EntryType; - -use crate::utils::normalize_path; -pub use crate::{ - config::{format_graphql, WasmerConfig}, - graphql::queries::get_bindings_query::ProgrammingLanguage, - package::Package, -}; - -pub static PACKAGE_TOML_FILE_NAME: &str = "wasmer.toml"; -pub static PACKAGE_TOML_FALLBACK_NAME: &str = "wapm.toml"; -pub static GLOBAL_CONFIG_FILE_NAME: &str = "wasmer.toml"; - -#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)] -#[non_exhaustive] -pub struct PackageDownloadInfo { - pub registry: String, - pub package: String, - pub version: String, - pub is_latest_version: bool, - /// Is the package private? - pub is_private: bool, - pub commands: String, - pub manifest: String, - pub url: String, - pub pirita_url: Option, -} - -pub fn query_command_from_registry( - registry_url: &str, - command_name: &str, -) -> Result { - use crate::graphql::{ - execute_query, - queries::{get_package_by_command_query, GetPackageByCommandQuery}, - }; - - let q = GetPackageByCommandQuery::build_query(get_package_by_command_query::Variables { - command_name: command_name.to_string(), - }); - - let response: get_package_by_command_query::ResponseData = execute_query(registry_url, "", &q) - .map_err(|e| format!("Error sending GetPackageByCommandQuery: {e}"))?; - - let command = response - .get_command - .ok_or_else(|| "GetPackageByCommandQuery: no get_command".to_string())?; - - let package = command.package_version.package.display_name; - let version = command.package_version.version; - let url = command.package_version.distribution.download_url; - let pirita_url = command.package_version.distribution.pirita_download_url; - - Ok(PackageDownloadInfo { - registry: registry_url.to_string(), - package, - version, - is_latest_version: command.package_version.is_last_version, - manifest: command.package_version.manifest, - commands: command_name.to_string(), - url, - pirita_url, - is_private: command.package_version.package.private, - }) -} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] -pub enum QueryPackageError { - ErrorSendingQuery(String), - NoPackageFound { - name: String, - version: Option, - }, -} - -impl fmt::Display for QueryPackageError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self { - QueryPackageError::ErrorSendingQuery(q) => write!(f, "error sending query: {q}"), - QueryPackageError::NoPackageFound { name, version } => { - write!(f, "no package found for {name:?}")?; - if let Some(version) = version { - write!(f, " (version = {version:?})")?; - } - - Ok(()) - } - } - } -} - -impl std::error::Error for QueryPackageError {} - -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd)] -pub enum GetIfPackageHasNewVersionResult { - // if version = Some(...) and the ~/.wasmer/checkouts/.../{version} exists, the package is already installed - UseLocalAlreadyInstalled { - registry_host: String, - namespace: String, - name: String, - version: String, - path: PathBuf, - }, - // if version = None, check for the latest version - LocalVersionMayBeOutdated { - registry_host: String, - namespace: String, - name: String, - /// Versions that are already installed + whether they are - /// older (true) or younger (false) than the timeout - installed_versions: Vec<(String, bool)>, - }, - // registry / namespace / name / version doesn't exist yet - PackageNotInstalledYet { - registry_url: String, - namespace: String, - name: String, - version: Option, - }, -} - -/// Returns the download info of the packages, on error returns all the available packages -/// i.e. (("foo/python", "wasmer.io"), ("bar/python" "wasmer.io"))) -pub fn query_package_from_registry( - registry_url: &str, - name: &str, - version: Option<&str>, - auth_token: Option<&str>, -) -> Result { - use crate::graphql::{ - execute_query, - queries::{get_package_version_query, GetPackageVersionQuery}, - }; - - let q = GetPackageVersionQuery::build_query(get_package_version_query::Variables { - name: name.to_string(), - version: version.map(|s| s.to_string()), - }); - - let response: get_package_version_query::ResponseData = - execute_query(registry_url, auth_token.unwrap_or_default(), &q).map_err(|e| { - QueryPackageError::ErrorSendingQuery(format!("Error sending GetPackagesQuery: {e}")) - })?; - - let v = response - .package_version - .as_ref() - .ok_or_else(|| QueryPackageError::NoPackageFound { - name: name.to_string(), - version: None, - })?; - - let manifest = - toml::from_str::(&v.manifest).map_err(|e| { - QueryPackageError::ErrorSendingQuery(format!( - "Invalid manifest for crate {name:?}: {e}" - )) - })?; - - Ok(PackageDownloadInfo { - registry: registry_url.to_string(), - package: v.package.name.clone(), - - version: v.version.clone(), - is_latest_version: v.is_last_version, - is_private: v.package.private, - manifest: v.manifest.clone(), - - commands: manifest - .commands - .iter() - .map(|s| s.get_name()) - .collect::>() - .join(", "), - - url: v.distribution.download_url.clone(), - pirita_url: v.distribution.pirita_download_url.clone(), - }) -} - -pub fn get_checkouts_dir(wasmer_dir: &Path) -> PathBuf { - wasmer_dir.join("checkouts") -} - -pub fn get_webc_dir(wasmer_dir: &Path) -> PathBuf { - wasmer_dir.join("webc") -} - -/// Convenience function that will unpack .tar.gz files and .tar.bz -/// files to a target directory (does NOT remove the original .tar.gz) -pub fn try_unpack_targz>( - target_targz_path: P, - target_path: P, - strip_toplevel: bool, -) -> Result { - let target_targz_path = target_targz_path.as_ref().to_string_lossy().to_string(); - let target_targz_path = crate::utils::normalize_path(&target_targz_path); - let target_targz_path = Path::new(&target_targz_path); - - let target_path = target_path.as_ref().to_string_lossy().to_string(); - let target_path = crate::utils::normalize_path(&target_path); - let target_path = Path::new(&target_path); - - let open_file = || { - std::fs::File::open(target_targz_path) - .map_err(|e| anyhow::anyhow!("failed to open {}: {e}", target_targz_path.display())) - }; - - let try_decode_gz = || { - let file = open_file()?; - let gz_decoded = flate2::read::GzDecoder::new(&file); - let ar = tar::Archive::new(gz_decoded); - if strip_toplevel { - unpack_sans_parent(ar, target_path).map_err(|e| { - anyhow::anyhow!( - "failed to unpack (gz_ar_unpack_sans_parent) {}: {e}", - target_targz_path.display() - ) - }) - } else { - unpack_with_parent(ar, target_path).map_err(|e| { - anyhow::anyhow!( - "failed to unpack (gz_ar_unpack) {}: {e}", - target_targz_path.display() - ) - }) - } - }; - - let try_decode_xz = || { - let file = open_file()?; - let mut decomp: Vec = Vec::new(); - let mut bufread = std::io::BufReader::new(&file); - lzma_rs::xz_decompress(&mut bufread, &mut decomp).map_err(|e| { - anyhow::anyhow!( - "failed to unpack (try_decode_xz) {}: {e}", - target_targz_path.display() - ) - })?; - - let cursor = std::io::Cursor::new(decomp); - let mut ar = tar::Archive::new(cursor); - if strip_toplevel { - unpack_sans_parent(ar, target_path).map_err(|e| { - anyhow::anyhow!( - "failed to unpack (sans parent) {}: {e}", - target_targz_path.display() - ) - }) - } else { - ar.unpack(target_path).map_err(|e| { - anyhow::anyhow!( - "failed to unpack (with parent) {}: {e}", - target_targz_path.display() - ) - }) - } - }; - - try_decode_gz().or_else(|e1| { - try_decode_xz() - .map_err(|e2| anyhow::anyhow!("could not decode gz: {e1}, could not decode xz: {e2}")) - })?; - - Ok(Path::new(&target_targz_path).to_path_buf()) -} - -/// Whether the top-level directory should be stripped -pub fn download_and_unpack_targz( - url: &str, - target_path: &Path, - strip_toplevel: bool, -) -> Result { - let tempdir = tempfile::TempDir::new()?; - - let target_targz_path = tempdir.path().join("package.tar.gz"); - - let mut resp = reqwest::blocking::get(url) - .map_err(|e| anyhow::anyhow!("failed to download {url}: {e}"))?; - - { - let mut file = std::fs::File::create(&target_targz_path).map_err(|e| { - anyhow::anyhow!( - "failed to download {url} into {}: {e}", - target_targz_path.display() - ) - })?; - - resp.copy_to(&mut file) - .map_err(|e| anyhow::anyhow!("{e}"))?; - } - - try_unpack_targz(target_targz_path.as_path(), target_path, strip_toplevel) - .with_context(|| anyhow::anyhow!("Could not download {url}"))?; - - Ok(target_path.to_path_buf()) -} - -pub fn unpack_with_parent(mut archive: tar::Archive, dst: &Path) -> Result<(), anyhow::Error> -where - R: std::io::Read, -{ - use std::path::Component::Normal; - - let dst_normalized = normalize_path(dst.to_string_lossy().as_ref()); - - for entry in archive.entries()? { - let mut entry = entry?; - let path: PathBuf = entry - .path()? - .components() - .skip(1) // strip top-level directory - .filter(|c| matches!(c, Normal(_))) // prevent traversal attacks - .collect(); - if entry.header().entry_type().is_file() { - entry.unpack_in(&dst_normalized)?; - } else if entry.header().entry_type() == EntryType::Directory { - std::fs::create_dir_all(Path::new(&dst_normalized).join(&path))?; - } - } - Ok(()) -} - -pub fn unpack_sans_parent(mut archive: tar::Archive, dst: &Path) -> std::io::Result<()> -where - R: std::io::Read, -{ - use std::path::Component::Normal; - - let dst_normalized = normalize_path(dst.to_string_lossy().as_ref()); - - for entry in archive.entries()? { - let mut entry = entry?; - let path: PathBuf = entry - .path()? - .components() - .skip(1) // strip top-level directory - .filter(|c| matches!(c, Normal(_))) // prevent traversal attacks - .collect(); - entry.unpack(Path::new(&dst_normalized).join(path))?; - } - Ok(()) -} - -pub fn whoami( - wasmer_dir: &Path, - registry: Option<&str>, - token: Option<&str>, -) -> Result<(String, String), anyhow::Error> { - use crate::graphql::queries::{who_am_i_query, WhoAmIQuery}; - - let config = WasmerConfig::from_file(wasmer_dir); - - let config = config - .map_err(|e| anyhow::anyhow!("{e}")) - .with_context(|| format!("{registry:?}"))?; - - let registry = match registry { - Some(s) => format_graphql(s), - None => config.registry.get_current_registry(), - }; - - let login_token = token - .map(|s| s.to_string()) - .or_else(|| config.registry.get_login_token_for_registry(®istry)) - .ok_or_else(|| anyhow::anyhow!("not logged into registry {:?}", registry))?; - - let q = WhoAmIQuery::build_query(who_am_i_query::Variables {}); - let response: who_am_i_query::ResponseData = - crate::graphql::execute_query(®istry, &login_token, &q) - .with_context(|| format!("{registry:?}"))?; - - let username = response - .viewer - .as_ref() - .ok_or_else(|| anyhow::anyhow!("not logged into registry {:?}", registry))? - .username - .to_string(); - - Ok((registry, username)) -} - -pub fn test_if_registry_present(registry: &str) -> Result { - use crate::graphql::queries::{test_if_registry_present, TestIfRegistryPresent}; - - let q = TestIfRegistryPresent::build_query(test_if_registry_present::Variables {}); - crate::graphql::execute_query_modifier_inner_check_json( - registry, - "", - &q, - Some(Duration::from_secs(1)), - |f| f, - ) - .map_err(|e| format!("{e}"))?; - - Ok(true) -} - -pub fn get_all_available_registries(wasmer_dir: &Path) -> Result, String> { - let config = WasmerConfig::from_file(wasmer_dir)?; - let mut registries = Vec::new(); - for login in config.registry.tokens { - registries.push(format_graphql(&login.registry)); - } - Ok(registries) -} - -/// A library that exposes bindings to a Wasmer package. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Bindings { - /// A unique ID specifying this set of bindings. - pub id: String, - /// The URL which can be used to download the files that were generated - /// (typically as a `*.tar.gz` file). - pub url: String, - /// The programming language these bindings are written in. - pub language: ProgrammingLanguage, - /// The generator used to generate these bindings. - pub generator: BindingsGenerator, -} - -/// The generator used to create [`Bindings`]. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct BindingsGenerator { - /// A unique ID specifying this generator. - pub id: String, - /// The generator package's name (e.g. `wasmer/wasmer-pack`). - pub package_name: String, - /// The exact package version. - pub version: String, - /// The name of the command that was used for generating bindings. - pub command: String, -} - -impl fmt::Display for BindingsGenerator { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let BindingsGenerator { - package_name, - version, - command, - .. - } = self; - - write!(f, "{package_name}@{version}:{command}")?; - - Ok(()) - } -} - -/// List all bindings associated with a particular package. -/// -/// If a version number isn't provided, this will default to the most recently -/// published version. -pub fn list_bindings( - registry: &str, - name: &str, - version: Option<&str>, -) -> Result, anyhow::Error> { - use crate::graphql::queries::{ - get_bindings_query::{ResponseData, Variables}, - GetBindingsQuery, - }; - - let variables = Variables { - name: name.to_string(), - version: version.map(String::from), - }; - - let q = GetBindingsQuery::build_query(variables); - let response: ResponseData = crate::graphql::execute_query(registry, "", &q)?; - - let package_version = response.package_version.context("Package not found")?; - - let mut bindings_packages = Vec::new(); - - for b in package_version.bindings.into_iter().flatten() { - let pkg = Bindings { - id: b.id, - url: b.url, - language: b.language, - generator: BindingsGenerator { - id: b.generator.package_version.id, - package_name: b.generator.package_version.package.name, - version: b.generator.package_version.version, - command: b.generator.command_name, - }, - }; - bindings_packages.push(pkg); - } - - Ok(bindings_packages) -} diff --git a/lib/registry/src/login.rs b/lib/registry/src/login.rs deleted file mode 100644 index 9803f6f6229..00000000000 --- a/lib/registry/src/login.rs +++ /dev/null @@ -1,25 +0,0 @@ -use crate::config::{format_graphql, UpdateRegistry}; -use crate::WasmerConfig; -use std::path::Path; - -/// Login to a registry and save the token associated with it. -/// -/// Also sets the registry as the currently active registry to provide a better UX. -pub fn login_and_save_token( - wasmer_dir: &Path, - registry: &str, - token: &str, -) -> Result, anyhow::Error> { - let registry = format_graphql(registry); - let mut config = WasmerConfig::from_file(wasmer_dir) - .map_err(|e| anyhow::anyhow!("config from file: {e}"))?; - config.registry.set_current_registry(®istry); - config.registry.set_login_token_for_registry( - &config.registry.get_current_registry(), - token, - UpdateRegistry::Update, - ); - let path = WasmerConfig::get_file_location(wasmer_dir); - config.save(path)?; - crate::utils::get_username_registry_token(®istry, token) -} diff --git a/lib/registry/src/package/builder.rs b/lib/registry/src/package/builder.rs deleted file mode 100644 index c16b9239f2e..00000000000 --- a/lib/registry/src/package/builder.rs +++ /dev/null @@ -1,1096 +0,0 @@ -use std::io::{self, Write}; -use std::path::{Path, PathBuf}; -use std::time::Duration; -use std::{fs, io::IsTerminal}; - -use anyhow::{anyhow, bail, Context}; -use flate2::{write::GzEncoder, Compression}; -use rusqlite::{params, Connection, OpenFlags, TransactionBehavior}; -use tar::Builder; -use thiserror::Error; -use time::{self, OffsetDateTime}; -use wasmer_config::package::{PackageIdent, MANIFEST_FILE_NAME}; - -use crate::publish::PublishWait; -use crate::WasmerConfig; -use crate::{package::builder::validate::ValidationPolicy, publish::SignArchiveResult}; - -const MIGRATIONS: &[(i32, &str)] = &[ - (0, include_str!("./sql/migrations/0000.sql")), - (1, include_str!("./sql/migrations/0001.sql")), - (2, include_str!("./sql/migrations/0002.sql")), -]; - -const CURRENT_DATA_VERSION: usize = MIGRATIONS.len(); - -/// An abstraction for the action of publishing a named or unnamed package. -#[derive(Debug)] -pub struct Publish { - /// Registry to publish to - pub registry: Option, - /// Run the publish logic without sending anything to the registry server - pub dry_run: bool, - /// Run the publish command without any output - pub quiet: bool, - /// Override the namespace of the package to upload - pub package_namespace: Option, - /// Override the name of the package to upload - pub package_name: Option, - /// Override the package version of the uploaded package in the wasmer.toml - pub version: Option, - /// The auth token to use. - pub token: String, - /// Skip validation of the uploaded package - pub no_validate: bool, - /// Directory containing the `wasmer.toml` (defaults to current root dir) - pub package_path: Option, - /// Wait for package to be available on the registry before exiting - pub wait: PublishWait, - /// Timeout (in seconds) for the publish query to the registry - pub timeout: Duration, -} - -#[derive(Debug, Error)] -enum PackageBuildError { - #[error("Unable to publish the \"{module}\" module because \"{}\" is not a file", path.display())] - SourceMustBeFile { module: String, path: PathBuf }, - #[error("Unable to load the bindings for \"{module}\" because \"{}\" doesn't exist", path.display())] - MissingBindings { module: String, path: PathBuf }, - #[error("Error building package when parsing module \"{0}\": {1}.")] - ErrorBuildingPackage(String, io::Error), - #[error( - "Path \"{0}\", specified in the manifest as part of the package file system does not exist.", - )] - MissingManifestFsPath(String), - #[error("When processing the package filesystem, found path \"{0}\" which is not a directory")] - PackageFileSystemEntryMustBeDirectory(String), -} - -impl Publish { - /// Publish the package to the selected (or default) registry. - pub async fn execute(&self) -> Result, anyhow::Error> { - let input_path = match self.package_path.as_ref() { - Some(s) => std::env::current_dir()?.join(s), - None => std::env::current_dir()?, - }; - - let manifest_path = match input_path.metadata() { - Ok(metadata) => { - if metadata.is_dir() { - let p = input_path.join("wasmer.toml"); - if !p.is_file() { - bail!( - "directory does not contain a 'wasmer.toml' manifest - use 'wasmer init' to initialize a new packagae, or specify a valid package directory or manifest file instead. (path: {})", - input_path.display() - ); - } - - p - } else if metadata.is_file() { - if input_path.extension().and_then(|x| x.to_str()) != Some("toml") { - bail!( - "The specified file path is not a .toml file: '{}'", - input_path.display() - ); - } - input_path - } else { - bail!("Invalid path specified: '{}'", input_path.display()); - } - } - Err(err) if err.kind() == std::io::ErrorKind::NotFound => { - bail!("Specified path does not exist: '{}'", input_path.display()); - } - Err(err) => { - bail!("Could not read path '{}': {}", input_path.display(), err); - } - }; - - let manifest = std::fs::read_to_string(&manifest_path) - .map_err(|e| anyhow::anyhow!("could not find manifest: {e}")) - .with_context(|| anyhow::anyhow!("{}", manifest_path.display()))?; - let mut manifest = wasmer_config::package::Manifest::parse(&manifest)?; - - let manifest_path_canon = manifest_path.canonicalize()?; - let manifest_dir = manifest_path_canon - .parent() - .context("could not determine manifest parent directory")? - .to_owned(); - - if let Some(package_name) = self.package_name.as_ref() { - if let Some(ref mut package) = manifest.package { - package.name = Some(package_name.clone()); - } - } - - if let Some(version) = self.version.as_ref() { - if let Some(ref mut package) = manifest.package { - package.version = Some(version.clone()); - } - } - - let archive_dir = tempfile::TempDir::new()?; - let archive_meta = construct_tar_gz(archive_dir.path(), &manifest, &manifest_path)?; - - let registry = match self.registry.as_deref() { - Some(s) => crate::format_graphql(s), - None => { - let wasmer_dir = WasmerConfig::get_wasmer_dir() - .map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?; - let config = WasmerConfig::from_file(&wasmer_dir) - .map_err(|e| anyhow::anyhow!("could not load config {e}"))?; - config.registry.get_current_registry() - } - }; - - let mut policy = self.validation_policy(); - - if !policy.skip_validation() { - validate::validate_directory( - &manifest, - ®istry, - manifest_dir, - &mut *policy, - &self.token, - )?; - } - - let archive_path = &archive_meta.archive_path; - let mut compressed_archive_reader = fs::File::open(archive_path)?; - - let maybe_signature_data = sign_compressed_archive(&mut compressed_archive_reader)?; - let archived_data_size = archive_path.metadata()?.len(); - - assert!(archive_path.exists()); - assert!(archive_path.is_file()); - - if self.dry_run { - // dry run: publish is done here - println!("🚀 Package published successfully!"); - - let path = archive_dir.into_path(); - eprintln!("Archive persisted at: {}", path.display()); - - log::info!( - "Publish succeeded, but package was not published because it was run in dry-run mode" - ); - - return Ok(None); - } - - crate::publish::try_chunked_uploading( - Some(registry), - Some(self.token.clone()), - &manifest.package, - &archive_meta.manifest_toml, - &archive_meta.license, - &archive_meta.readme, - &archive_meta - .archive_path - .file_name() - .unwrap() - .to_str() - .unwrap() - .to_string(), - archive_path, - &maybe_signature_data, - archived_data_size, - self.quiet, - self.wait, - self.timeout, - self.package_namespace.clone(), - ) - .await - } - - fn validation_policy(&self) -> Box { - if self.no_validate { - Box::::default() - } else if std::io::stdin().is_terminal() { - Box::::default() - } else { - Box::::default() - } - } -} - -struct ConstructedPackageArchive { - manifest_toml: String, - readme: Option, - license: Option, - archive_path: PathBuf, -} - -fn construct_tar_gz( - archive_dir: &Path, - manifest: &wasmer_config::package::Manifest, - manifest_path: &Path, -) -> Result { - // This is an assert instead of returned error because this is a programmer error. - debug_assert!(manifest_path.is_file(), "manifest path is not a file"); - - let manifest_dir = manifest_path - .parent() - .context("manifest path has no parent directory")?; - - let mut builder = Builder::new(Vec::new()); - builder.append_path_with_name( - manifest_path, - manifest_path - .file_name() - .map(|s| s.to_str().unwrap_or_default()) - .unwrap_or(MANIFEST_FILE_NAME), - )?; - - let manifest_string = toml::to_string(&manifest)?; - - let modules = &manifest.modules; - - let readme = if let Some(ref package) = manifest.package { - match package.readme.as_ref() { - None => None, - Some(s) => { - let path = - append_path_to_tar_gz(&mut builder, manifest_dir, s).map_err(|(p, e)| { - PackageBuildError::ErrorBuildingPackage(format!("{}", p.display()), e) - })?; - Some(std::fs::read_to_string(path)?) - } - } - } else { - None - }; - - let license = if let Some(ref package) = manifest.package { - match package.license_file.as_ref() { - None => None, - Some(s) => { - let path = - append_path_to_tar_gz(&mut builder, manifest_dir, s).map_err(|(p, e)| { - PackageBuildError::ErrorBuildingPackage(format!("{}", p.display()), e) - })?; - Some(std::fs::read_to_string(path)?) - } - } - } else { - None - }; - - for module in modules { - append_path_to_tar_gz(&mut builder, manifest_dir, &module.source).map_err( - |(normalized_path, _)| PackageBuildError::SourceMustBeFile { - module: module.name.clone(), - path: normalized_path, - }, - )?; - - if let Some(bindings) = &module.bindings { - for path in bindings.referenced_files(manifest_dir)? { - let relative_path = path.strip_prefix(manifest_dir).with_context(|| { - format!( - "\"{}\" should be inside \"{}\"", - path.display(), - manifest_dir.display(), - ) - })?; - - append_path_to_tar_gz(&mut builder, manifest_dir, relative_path).map_err( - |(normalized_path, _)| PackageBuildError::MissingBindings { - module: module.name.clone(), - path: normalized_path, - }, - )?; - } - } - } - - // bundle the package filesystem - for (_alias, path) in &manifest.fs { - let normalized_path = normalize_path(manifest_dir, path); - let path_metadata = normalized_path.metadata().map_err(|_| { - PackageBuildError::MissingManifestFsPath(normalized_path.to_string_lossy().to_string()) - })?; - if path_metadata.is_dir() { - builder.append_dir_all(path, &normalized_path) - } else { - return Err(PackageBuildError::PackageFileSystemEntryMustBeDirectory( - path.to_string_lossy().to_string(), - ) - .into()); - } - .map_err(|_| { - PackageBuildError::MissingManifestFsPath(normalized_path.to_string_lossy().to_string()) - })?; - } - - builder - .finish() - .map_err(|e| anyhow::anyhow!("failed to finish .tar.gz builder: {e}"))?; - let tar_archive_data = builder.into_inner().expect("tar archive was not finalized"); - let archive_name = "package.tar.gz".to_string(); - fs::create_dir(archive_dir.join("wapm_package"))?; - let archive_path = archive_dir.join("wapm_package").join(archive_name); - let mut compressed_archive = fs::File::create(&archive_path).unwrap(); - let mut gz_enc = GzEncoder::new(&mut compressed_archive, Compression::best()); - - gz_enc.write_all(&tar_archive_data).unwrap(); - let _compressed_archive = gz_enc.finish().unwrap(); - - Ok(ConstructedPackageArchive { - manifest_toml: manifest_string, - archive_path, - readme, - license, - }) -} - -fn append_path_to_tar_gz( - builder: &mut tar::Builder>, - base_path: &Path, - target_path: &Path, -) -> Result { - let normalized_path = normalize_path(base_path, target_path); - normalized_path - .metadata() - .map_err(|e| (normalized_path.clone(), e))?; - builder - .append_path_with_name(&normalized_path, target_path) - .map_err(|e| (normalized_path.clone(), e))?; - Ok(normalized_path) -} - -fn normalize_path(cwd: &Path, path: &Path) -> PathBuf { - let mut out = PathBuf::from(cwd); - let mut components = path.components(); - if path.is_absolute() { - log::warn!( - "Interpreting absolute path {} as a relative path", - path.to_string_lossy() - ); - components.next(); - } - for comp in components { - out.push(comp); - } - out -} - -/// Takes the package archive as a File and attempts to sign it using the active key -/// returns the public key id used to sign it and the signature string itself -pub fn sign_compressed_archive( - compressed_archive: &mut fs::File, -) -> anyhow::Result { - let key_db = open_db()?; - let personal_key = if let Ok(v) = get_active_personal_key(&key_db) { - v - } else { - return Ok(SignArchiveResult::NoKeyRegistered); - }; - let password = rpassword::prompt_password(format!( - "Please enter your password for the key pair {}:", - &personal_key.public_key_id - )) - .ok(); - let private_key = if let Some(priv_key_location) = personal_key.private_key_location { - match minisign::SecretKey::from_file(&priv_key_location, password) { - Ok(priv_key_data) => priv_key_data, - Err(e) => { - log::error!( - "Could not read private key from location {}: {}", - priv_key_location, - e - ); - return Err(e.into()); - } - } - } else { - // TODO: add more info about why this might have happened and what the user can do about it - log::warn!("Active key does not have a private key location registered with it!"); - return Err(anyhow!("Cannot sign package, no private key")); - }; - let public_key = minisign::PublicKey::from_base64(&personal_key.public_key_value)?; - let signature = minisign::sign( - Some(&public_key), - &private_key, - compressed_archive, - None, - None, - )?; - Ok(SignArchiveResult::Ok { - public_key_id: personal_key.public_key_id, - signature: signature.to_string(), - }) -} - -/// Opens an exclusive read/write connection to the database, creating it if it does not exist -pub fn open_db() -> anyhow::Result { - let wasmer_dir = - WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("no wasmer dir: {e}"))?; - let db_path = WasmerConfig::get_database_file_path(&wasmer_dir); - let mut conn = Connection::open_with_flags( - db_path, - OpenFlags::SQLITE_OPEN_CREATE - | OpenFlags::SQLITE_OPEN_READ_WRITE - | OpenFlags::SQLITE_OPEN_FULL_MUTEX, - )?; - - apply_migrations(&mut conn)?; - Ok(conn) -} - -/// Applies migrations to the database -pub fn apply_migrations(conn: &mut Connection) -> anyhow::Result<()> { - let user_version = conn.pragma_query_value(None, "user_version", |val| val.get(0))?; - for data_version in user_version..CURRENT_DATA_VERSION { - log::debug!("Applying migration {}", data_version); - apply_migration(conn, data_version as i32)?; - } - Ok(()) -} - -#[derive(Debug, Error)] -enum MigrationError { - #[error( - "Critical internal error: the data version {0} is not handleded; current data version: {1}" - )] - MigrationNumberDoesNotExist(i32, i32), - #[error("Critical internal error: failed to commit trasaction migrating to data version {0}")] - CommitFailed(i32), - #[error("Critical internal error: transaction failed on migration number {0}: {1}")] - TransactionFailed(i32, String), -} - -/// Applies migrations to the database and updates the `user_version` pragma. -/// Every migration must leave the database in a valid state. -fn apply_migration(conn: &mut Connection, migration_number: i32) -> Result<(), MigrationError> { - let tx = conn - .transaction_with_behavior(TransactionBehavior::Immediate) - .map_err(|e| MigrationError::TransactionFailed(migration_number, format!("{}", e)))?; - - let migration_to_apply = MIGRATIONS - .iter() - .find_map(|(number, sql)| { - if *number == migration_number { - Some(sql) - } else { - None - } - }) - .ok_or({ - MigrationError::MigrationNumberDoesNotExist( - migration_number, - CURRENT_DATA_VERSION as i32, - ) - })?; - - tx.execute_batch(migration_to_apply) - .map_err(|e| MigrationError::TransactionFailed(migration_number, format!("{}", e)))?; - - tx.pragma_update(None, "user_version", migration_number + 1) - .map_err(|e| MigrationError::TransactionFailed(migration_number, format!("{}", e)))?; - tx.commit() - .map_err(|_| MigrationError::CommitFailed(migration_number)) -} - -/// Information about one of the user's keys -#[derive(Debug)] -pub struct PersonalKey { - /// Flag saying if the key will be used (there can only be one active key at a time) - pub active: bool, - /// The public key's tag. Used to identify the key pair - pub public_key_id: String, - /// The raw value of the public key in base64 - pub public_key_value: String, - /// The location in the file system of the private key - pub private_key_location: Option, - /// The type of private/public key this is - pub key_type_identifier: String, - /// The time at which the key was registered with wasmer - pub date_created: OffsetDateTime, -} - -fn get_active_personal_key(conn: &Connection) -> anyhow::Result { - let mut stmt = conn.prepare( - "SELECT active, public_key_value, private_key_location, date_added, key_type_identifier, public_key_id FROM personal_keys - where active = 1", - )?; - - let result = stmt - .query_map(params![], |row| { - Ok(PersonalKey { - active: row.get(0)?, - public_key_value: row.get(1)?, - private_key_location: row.get(2)?, - date_created: { - use time::format_description::well_known::Rfc3339; - let time_str: String = row.get(3)?; - OffsetDateTime::parse(&time_str, &Rfc3339) - .unwrap_or_else(|_| panic!("Failed to parse time string {}", &time_str)) - }, - key_type_identifier: row.get(4)?, - public_key_id: row.get(5)?, - }) - })? - .next(); - - if let Some(res) = result { - Ok(res?) - } else { - Err(anyhow!("No active key found")) - } -} - -mod interfaces { - use anyhow::anyhow; - use rusqlite::{params, Connection, TransactionBehavior}; - - pub const WASM_INTERFACE_EXISTENCE_CHECK: &str = - include_str!("./sql/queries/wasm_interface_existence_check.sql"); - pub const INSERT_WASM_INTERFACE: &str = include_str!("./sql/queries/insert_interface.sql"); - pub const GET_WASM_INTERFACE: &str = include_str!("./sql/queries/get_interface.sql"); - - pub fn interface_exists( - conn: &mut Connection, - interface_name: &str, - version: &str, - ) -> anyhow::Result { - let mut stmt = conn.prepare(WASM_INTERFACE_EXISTENCE_CHECK)?; - Ok(stmt.exists(params![interface_name, version])?) - } - - pub fn load_interface_from_db( - conn: &mut Connection, - interface_name: &str, - version: &str, - ) -> anyhow::Result { - let mut stmt = conn.prepare(GET_WASM_INTERFACE)?; - let interface_string: String = - stmt.query_row(params![interface_name, version], |row| row.get(0))?; - - wasmer_wasm_interface::parser::parse_interface(&interface_string).map_err(|e| { - anyhow!( - "Failed to parse interface {} version {} in database: {}", - interface_name, - version, - e - ) - }) - } - - pub fn import_interface( - conn: &mut Connection, - interface_name: &str, - version: &str, - content: &str, - ) -> anyhow::Result<()> { - // fail if we already have this interface - { - let mut key_check = conn.prepare(WASM_INTERFACE_EXISTENCE_CHECK)?; - let result = key_check.exists(params![interface_name, version])?; - - if result { - return Err(anyhow!( - "Interface {}, version {} already exists", - interface_name, - version - )); - } - } - - let tx = conn.transaction_with_behavior(TransactionBehavior::Immediate)?; - let time_string = get_current_time_in_format().expect("Could not get current time"); - - log::debug!("Adding interface {:?} {:?}", interface_name, version); - tx.execute( - INSERT_WASM_INTERFACE, - params![interface_name, version, time_string, content], - )?; - - tx.commit()?; - Ok(()) - } - - /// Gets the current time in our standard format - pub fn get_current_time_in_format() -> Option { - use time::format_description::well_known::Rfc3339; - let cur_time = time::OffsetDateTime::now_utc(); - cur_time.format(&Rfc3339).ok() - } -} - -mod validate { - use anyhow::anyhow; - use thiserror::Error; - use wasmer_wasm_interface::{validate, Interface}; - use wasmparser::WasmFeatures; - - use super::interfaces; - use crate::{interface::InterfaceFromServer, QueryPackageError}; - use std::{ - fs, - io::Read, - ops::ControlFlow, - path::{Path, PathBuf}, - }; - - pub(crate) fn validate_directory( - manifest: &wasmer_config::package::Manifest, - registry: &str, - pkg_path: PathBuf, - callbacks: &mut dyn ValidationPolicy, - auth_token: &str, - ) -> anyhow::Result<()> { - // validate as dir - for module in manifest.modules.iter() { - if let Err(e) = validate_module(module, registry, &pkg_path) { - if callbacks.on_invalid_module(module, &e).is_break() { - return Err(e.into()); - } - } - } - - if would_change_package_privacy(manifest, registry, auth_token)? - && callbacks.on_package_privacy_changed(manifest).is_break() - { - if let Some(package) = &manifest.package { - if package.private { - return Err(ValidationError::WouldBecomePrivate.into()); - } else { - return Err(ValidationError::WouldBecomePublic.into()); - } - } - } - - log::debug!("package at path {:#?} validated", &pkg_path); - - Ok(()) - } - - /// Check if publishing this manifest would change the package's privacy. - fn would_change_package_privacy( - manifest: &wasmer_config::package::Manifest, - registry: &str, - auth_token: &str, - ) -> Result { - match &manifest.package { - Some(pkg) => { - if let Some(ref name) = pkg.name { - let result = - crate::query_package_from_registry(registry, name, None, Some(auth_token)); - - match result { - Ok(package_version) => Ok(package_version.is_private != pkg.private), - Err(QueryPackageError::NoPackageFound { .. }) => { - // The package hasn't been published yet - Ok(false) - } - Err(e) => Err(e.into()), - } - } else { - Ok(false) - } - } - - // This manifest refers to an unnamed package: - // as of now, unnamed packages are private by default. - None => Ok(false), - } - } - - fn validate_module( - module: &wasmer_config::package::Module, - registry: &str, - pkg_path: &Path, - ) -> Result<(), ValidationError> { - let source_path = if module.source.is_relative() { - pkg_path.join(&module.source) - } else { - module.source.clone() - }; - let source_path_string = source_path.to_string_lossy().to_string(); - let mut wasm_file = - fs::File::open(&source_path).map_err(|_| ValidationError::MissingFile { - file: source_path_string.clone(), - })?; - let mut wasm_buffer = Vec::new(); - wasm_file - .read_to_end(&mut wasm_buffer) - .map_err(|err| ValidationError::MiscCannotRead { - file: source_path_string.clone(), - error: format!("{}", err), - })?; - - if let Some(bindings) = &module.bindings { - validate_bindings(bindings, pkg_path)?; - } - - // hack, short circuit if no interface for now - if module.interfaces.is_none() { - return validate_wasm_and_report_errors_old(&wasm_buffer[..], source_path_string); - } - - let mut conn = super::open_db().map_err(ValidationError::UpdatingInterfaces)?; - let mut interface: Interface = Default::default(); - for (interface_name, interface_version) in - module.interfaces.clone().unwrap_or_default().into_iter() - { - add_module_interface( - &mut conn, - interface_name, - interface_version, - registry, - &mut interface, - ) - .map_err(ValidationError::UpdatingInterfaces)?; - } - validate::validate_wasm_and_report_errors(&wasm_buffer, &interface).map_err(|e| { - ValidationError::InvalidWasm { - file: source_path_string, - error: format!("{:?}", e), - } - })?; - - Ok(()) - } - - fn add_module_interface( - conn: &mut rusqlite::Connection, - interface_name: String, - interface_version: String, - registry: &str, - interface: &mut Interface, - ) -> anyhow::Result<()> { - if !interfaces::interface_exists(conn, &interface_name, &interface_version)? { - // download interface and store it if we don't have it locally - let interface_data_from_server = InterfaceFromServer::get( - registry, - interface_name.clone(), - interface_version.clone(), - )?; - interfaces::import_interface( - conn, - &interface_name, - &interface_version, - &interface_data_from_server.content, - )?; - } - let sub_interface = - interfaces::load_interface_from_db(conn, &interface_name, &interface_version)?; - *interface = interface - .merge(sub_interface) - .map_err(|e| anyhow!("Failed to merge interface {}: {}", &interface_name, e))?; - Ok(()) - } - - fn validate_bindings( - bindings: &wasmer_config::package::Bindings, - base_directory_path: &Path, - ) -> Result<(), ValidationError> { - // Note: checking for referenced files will make sure they all exist. - let _ = bindings.referenced_files(base_directory_path)?; - - Ok(()) - } - - #[derive(Debug, Error)] - #[non_exhaustive] - pub enum ValidationError { - #[error("WASM file \"{file}\" detected as invalid because {error}")] - InvalidWasm { file: String, error: String }, - #[error("Could not find file {file}")] - MissingFile { file: String }, - #[error("Failed to read file {file}; {error}")] - MiscCannotRead { file: String, error: String }, - #[error(transparent)] - Imports(#[from] wasmer_config::package::ImportsError), - #[error("Unable to update the interfaces database")] - UpdatingInterfaces(#[source] anyhow::Error), - #[error("Aborting because publishing the package would make it public")] - WouldBecomePublic, - #[error("Aborting because publishing the package would make it private")] - WouldBecomePrivate, - #[error("Unable to look up package information")] - Registry(#[from] QueryPackageError), - } - - // legacy function, validates wasm. TODO: clean up - pub fn validate_wasm_and_report_errors_old( - wasm: &[u8], - file_name: String, - ) -> Result<(), ValidationError> { - let mut wasm_features = WasmFeatures::empty(); - wasm_features.set(WasmFeatures::THREADS, true); - wasm_features.set(WasmFeatures::REFERENCE_TYPES, true); - wasm_features.set(WasmFeatures::SIMD, true); - wasm_features.set(WasmFeatures::BULK_MEMORY, true); - wasm_features.set(WasmFeatures::MULTI_VALUE, true); - - let mut val = wasmparser::Validator::new_with_features(wasm_features); - - val.validate_all(wasm) - .map_err(|e| ValidationError::InvalidWasm { - file: file_name.clone(), - error: format!("{}", e), - })?; - - Ok(()) - } - - /// How should validation be treated by the publishing process? - pub(crate) trait ValidationPolicy: Send + Sync { - /// Should validation be skipped entirely? - fn skip_validation(&mut self) -> bool; - - /// How should publishing proceed when a module is invalid? - fn on_invalid_module( - &mut self, - module: &wasmer_config::package::Module, - error: &ValidationError, - ) -> ControlFlow<(), ()>; - - /// How should publishing proceed when it might change a package's - /// privacy? (i.e. by making a private package publicly available). - fn on_package_privacy_changed( - &mut self, - manifest: &wasmer_config::package::Manifest, - ) -> ControlFlow<(), ()>; - } - - #[derive(Debug, Default, Copy, Clone, PartialEq)] - pub(crate) struct Skip; - - impl ValidationPolicy for Skip { - fn skip_validation(&mut self) -> bool { - true - } - - fn on_invalid_module( - &mut self, - _module: &wasmer_config::package::Module, - _error: &ValidationError, - ) -> ControlFlow<(), ()> { - unreachable!() - } - - fn on_package_privacy_changed( - &mut self, - _manifest: &wasmer_config::package::Manifest, - ) -> ControlFlow<(), ()> { - unreachable!() - } - } - - #[derive(Debug, Default, Copy, Clone, PartialEq)] - pub(crate) struct Interactive; - - impl ValidationPolicy for Interactive { - fn skip_validation(&mut self) -> bool { - false - } - - fn on_invalid_module( - &mut self, - module: &wasmer_config::package::Module, - error: &ValidationError, - ) -> ControlFlow<(), ()> { - let module_name = &module.name; - let prompt = - format!("Validation error with the \"{module_name}\" module: {error}. Would you like to continue?"); - - match dialoguer::Confirm::new() - .with_prompt(prompt) - .default(false) - .interact() - { - Ok(true) => ControlFlow::Continue(()), - Ok(false) => ControlFlow::Break(()), - Err(e) => { - tracing::error!( - error = &e as &dyn std::error::Error, - "Unable to check whether the user wants to change the package's privacy", - ); - ControlFlow::Break(()) - } - } - } - - fn on_package_privacy_changed( - &mut self, - manifest: &wasmer_config::package::Manifest, - ) -> ControlFlow<(), ()> { - if let Some(pkg) = &manifest.package { - let privacy = if pkg.private { "private" } else { "public" }; - let prompt = - format!("This will make the package {privacy}. Would you like to continue?"); - - match dialoguer::Confirm::new() - .with_prompt(prompt) - .default(false) - .interact() - { - Ok(true) => ControlFlow::Continue(()), - Ok(false) => ControlFlow::Break(()), - Err(e) => { - tracing::error!( - error = &e as &dyn std::error::Error, - "Unable to check whether the user wants to change the package's privacy", - ); - ControlFlow::Break(()) - } - } - } else { - ControlFlow::Continue(()) - } - } - } - - #[derive(Debug, Default, Copy, Clone, PartialEq)] - pub(crate) struct NonInteractive; - - impl ValidationPolicy for NonInteractive { - fn skip_validation(&mut self) -> bool { - false - } - - fn on_invalid_module( - &mut self, - _module: &wasmer_config::package::Module, - _error: &ValidationError, - ) -> ControlFlow<(), ()> { - ControlFlow::Break(()) - } - - fn on_package_privacy_changed( - &mut self, - _manifest: &wasmer_config::package::Manifest, - ) -> ControlFlow<(), ()> { - ControlFlow::Break(()) - } - } -} - -#[cfg(test)] -mod tests { - use std::io::Read; - - use super::*; - - #[test] - fn test_construct_package_tar_gz() { - let manifest_str = r#"[package] -name = "wasmer-tests/wcgi-always-panic" -version = "0.6.0" -description = "wasmer-tests/wcgi-always-panic website" - -[[module]] -name = "wcgi-always-panic" -source = "module.wasm" -abi = "wasi" - -[[command]] -name = "wcgi" -module = "wcgi-always-panic" -runner = "https://webc.org/runner/wcgi" -"#; - - let archive_dir = tempfile::tempdir().unwrap(); - - let manifest_dir = tempfile::tempdir().unwrap(); - - let mp = manifest_dir.path(); - let manifest_path = mp.join("wasmer.toml"); - - std::fs::write(&manifest_path, manifest_str).unwrap(); - std::fs::write(mp.join("module.wasm"), "()").unwrap(); - - let manifest = wasmer_config::package::Manifest::parse(manifest_str).unwrap(); - - let meta = construct_tar_gz(archive_dir.path(), &manifest, &manifest_path).unwrap(); - - let mut data = std::io::Cursor::new(std::fs::read(meta.archive_path).unwrap()); - - let gz = flate2::read::GzDecoder::new(&mut data); - let mut archive = tar::Archive::new(gz); - - let map = archive - .entries() - .unwrap() - .map(|res| { - let mut entry = res.unwrap(); - let name = entry.path().unwrap().to_str().unwrap().to_string(); - let mut contents = String::new(); - entry.read_to_string(&mut contents).unwrap(); - eprintln!("{name}:\n{contents}\n\n"); - (name, contents) - }) - .collect::>(); - - let expected: std::collections::HashMap = [ - ("wapm.toml".to_string(), manifest_str.to_string()), - ("module.wasm".to_string(), "()".to_string()), - ] - .into_iter() - .collect(); - - pretty_assertions::assert_eq!(map, expected); - } - - #[test] - fn test_construct_wai_package_tar_gz() { - let manifest_str = r#"[package] -name = "wasmer/crumsort-wasm" -version = "0.2.4" -description = "Crumsort from Google made for WASM" - -[[module]] -name = "crumsort-wasm" -source = "crumsort_wasm.wasm" - -[module.bindings] -wai-version = "0.2.0" -exports = "crum-sort.wai" -"#; - - let archive_dir = tempfile::tempdir().unwrap(); - - let manifest_dir = tempfile::tempdir().unwrap(); - - let mp = manifest_dir.path(); - let manifest_path = mp.join("wasmer.toml"); - - std::fs::write(&manifest_path, manifest_str).unwrap(); - std::fs::write(mp.join("crumsort_wasm.wasm"), "()").unwrap(); - std::fs::write(mp.join("crum-sort.wai"), "/// crum-sort.wai").unwrap(); - - let manifest = wasmer_config::package::Manifest::parse(manifest_str).unwrap(); - let meta = construct_tar_gz(archive_dir.path(), &manifest, &manifest_path).unwrap(); - - let mut data = std::io::Cursor::new(std::fs::read(meta.archive_path).unwrap()); - - let gz = flate2::read::GzDecoder::new(&mut data); - let mut archive = tar::Archive::new(gz); - - let map = archive - .entries() - .unwrap() - .map(|res| { - let mut entry = res.unwrap(); - let name = entry.path().unwrap().to_str().unwrap().to_string(); - let mut contents = String::new(); - entry.read_to_string(&mut contents).unwrap(); - eprintln!("{name}:\n{contents}\n\n"); - (name, contents) - }) - .collect::>(); - - let expected: std::collections::HashMap = [ - ("wapm.toml".to_string(), manifest_str.to_string()), - ("crum-sort.wai".to_string(), "/// crum-sort.wai".to_string()), - ("crumsort_wasm.wasm".to_string(), "()".to_string()), - ] - .into_iter() - .collect(); - - pretty_assertions::assert_eq!(map, expected); - } -} diff --git a/lib/registry/src/package/mod.rs b/lib/registry/src/package/mod.rs deleted file mode 100644 index 7296c0f4b9b..00000000000 --- a/lib/registry/src/package/mod.rs +++ /dev/null @@ -1,190 +0,0 @@ -#[cfg(feature = "build-package")] -pub mod builder; - -use crate::WasmerConfig; -use regex::Regex; -use std::path::{Path, PathBuf}; -use std::{fmt, str::FromStr}; -use url::Url; - -const REGEX_PACKAGE_WITH_VERSION: &str = - r"^([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)(@([a-zA-Z0-9\.\-_]+*))?$"; - -lazy_static::lazy_static! { - static ref PACKAGE_WITH_VERSION: Regex = regex::Regex::new(REGEX_PACKAGE_WITH_VERSION).unwrap(); -} - -#[derive(Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub struct Package { - pub namespace: String, - pub name: String, - pub version: Option, -} - -impl fmt::Display for Package { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "{}", self.file()) - } -} - -impl Package { - /// Checks whether the package is already installed, if yes, returns the path to the root dir - pub fn already_installed(&self, wasmer_dir: &Path) -> Option { - let checkouts_dir = crate::get_checkouts_dir(wasmer_dir); - let config = WasmerConfig::from_file(wasmer_dir).ok()?; - let current_registry = config.registry.get_current_registry(); - let hash = self.get_hash(¤t_registry); - - let found = std::fs::read_dir(&checkouts_dir) - .ok()? - .filter_map(|e| Some(e.ok()?.file_name().to_str()?.to_string())) - .find(|s| match self.version.as_ref() { - None => s.contains(&hash), - Some(v) => s.contains(&hash) && s.ends_with(v), - })?; - Some(checkouts_dir.join(found)) - } - - /// Checks if the URL is already installed, note that `{url}@{version}` - /// and `{url}` are treated the same - pub fn is_url_already_installed(url: &Url, wasmer_dir: &Path) -> Option { - let checkouts_dir = crate::get_checkouts_dir(wasmer_dir); - - let url_string = url.to_string(); - let (url, version) = match url_string.split('@').collect::>()[..] { - [url, version] => (url.to_string(), Some(version)), - _ => (url_string, None), - }; - let hash = Self::hash_url(&url); - let found = std::fs::read_dir(&checkouts_dir) - .ok()? - .filter_map(|e| Some(e.ok()?.file_name().to_str()?.to_string())) - .find(|s| match version.as_ref() { - None => s.contains(&hash), - Some(v) => s.contains(&hash) && s.ends_with(v), - })?; - Some(checkouts_dir.join(found)) - } - - /// Returns the hash of the URL with a maximum of 128 bytes length - /// (necessary for not erroring on filesystem limitations) - pub fn hash_url(url: &str) -> String { - hex::encode(url).chars().take(128).collect() - } - - /// Returns the hash of the URL with a maximum of 64 bytes length - pub fn unhash_url(hashed: &str) -> String { - String::from_utf8_lossy(&hex::decode(hashed).unwrap_or_default()).to_string() - } - - /// Returns the hash of the package URL without the version - /// (because the version is encoded as @version and isn't part of the hash itself) - pub fn get_hash(&self, registry: &str) -> String { - let url = self.get_url_without_version(registry); - Self::hash_url(&url.unwrap_or_default()) - } - - fn get_url_without_version(&self, registry: &str) -> Result { - let url = self.url(registry); - Ok(format!( - "{}/{}/{}", - url?.origin().ascii_serialization(), - self.namespace, - self.name - )) - } - - /// Returns the filename for this package - pub fn file(&self) -> String { - let version = self - .version - .as_ref() - .map(|f| format!("@{f}")) - .unwrap_or_default(); - format!("{}/{}{version}", self.namespace, self.name) - } - - /// Returns the {namespace}/{name} package name - pub fn package(&self) -> String { - format!("{}/{}", self.namespace, self.name) - } - - /// Returns the full URL including the version for this package - pub fn url(&self, registry: &str) -> Result { - let registry_tld = tldextract::TldExtractor::new(tldextract::TldOption::default()) - .extract(registry) - .map_err(|e| anyhow::anyhow!("Invalid registry: {}: {e}", registry))?; - - let registry_tld = format!( - "{}.{}", - registry_tld.domain.as_deref().unwrap_or(""), - registry_tld.suffix.as_deref().unwrap_or(""), - ); - - let version = self - .version - .as_ref() - .map(|f| format!("@{f}")) - .unwrap_or_default(); - let url = format!( - "https://{registry_tld}/{}/{}{version}", - self.namespace, self.name - ); - url::Url::parse(&url).map_err(|e| anyhow::anyhow!("error parsing {url}: {e}")) - } - - /// Returns the path to the installation directory. - /// Does not check whether the installation directory already exists. - pub fn get_path(&self, wasmer_dir: &Path) -> Result { - let checkouts_dir = crate::get_checkouts_dir(wasmer_dir); - let config = WasmerConfig::from_file(wasmer_dir) - .map_err(|e| anyhow::anyhow!("could not load config {e}"))?; - let hash = self.get_hash(&config.registry.get_current_registry()); - - match self.version.as_ref() { - Some(v) => Ok(checkouts_dir.join(format!("{}@{}", hash, v))), - None => Ok(checkouts_dir.join(&hash)), - } - } -} - -impl FromStr for Package { - type Err = anyhow::Error; - - fn from_str(s: &str) -> Result { - let captures = PACKAGE_WITH_VERSION - .captures(s.trim()) - .map(|c| { - c.iter() - .flatten() - .map(|m| m.as_str().to_owned()) - .collect::>() - }) - .unwrap_or_default(); - - match captures.len() { - // namespace/package - 3 => { - let namespace = captures[1].to_string(); - let name = captures[2].to_string(); - Ok(Package { - namespace, - name, - version: None, - }) - } - // namespace/package@version - 5 => { - let namespace = captures[1].to_string(); - let name = captures[2].to_string(); - let version = captures[4].to_string(); - Ok(Package { - namespace, - name, - version: Some(version), - }) - } - other => Err(anyhow::anyhow!("invalid package {other}")), - } - } -} diff --git a/lib/registry/src/package/sql/migrations/0000.sql b/lib/registry/src/package/sql/migrations/0000.sql deleted file mode 100644 index a527dbc4f29..00000000000 --- a/lib/registry/src/package/sql/migrations/0000.sql +++ /dev/null @@ -1,27 +0,0 @@ -CREATE TABLE personal_keys -( - id integer primary key, - active integer not null, - public_key_id text not null UNIQUE, - public_key_value text not null UNIQUE, - private_key_location text UNIQUE, - key_type_identifier text not null, - date_added text not null -); - -CREATE TABLE wapm_users -( - id integer primary key, - name text not null UNIQUE -); - -CREATE TABLE wapm_public_keys -( - id integer primary key, - public_key_id text not null UNIQUE, - user_key integer not null, - public_key_value text not null UNIQUE, - key_type_identifier text not null, - date_added text not null, - FOREIGN KEY(user_key) REFERENCES wapm_users(id) -); diff --git a/lib/registry/src/package/sql/migrations/0001.sql b/lib/registry/src/package/sql/migrations/0001.sql deleted file mode 100644 index 42587319156..00000000000 --- a/lib/registry/src/package/sql/migrations/0001.sql +++ /dev/null @@ -1,9 +0,0 @@ -CREATE TABLE wasm_contracts -( - id integer primary key, - contract_name text not null, - version text not null, - date_added text not null, - content text not null, - CONSTRAINT name_version_unique UNIQUE (contract_name, version) -); diff --git a/lib/registry/src/package/sql/migrations/0002.sql b/lib/registry/src/package/sql/migrations/0002.sql deleted file mode 100644 index cc57ff9b8ee..00000000000 --- a/lib/registry/src/package/sql/migrations/0002.sql +++ /dev/null @@ -1,26 +0,0 @@ -PRAGMA foreign_keys=off; - -CREATE TABLE wasm_interfaces -( - id integer primary key, - interface_name text not null, - version text not null, - date_added text not null, - content text not null, - CONSTRAINT name_version_unique UNIQUE (interface_name, version) -); - -INSERT INTO wasm_interfaces -( - id, - interface_name, - version, - date_added, - content -) - SELECT id, contract_name, version, date_added, content - FROM wasm_contracts; - -DROP TABLE wasm_contracts; - -PRAGMA foreign_keys=on; diff --git a/lib/registry/src/package/sql/queries/get_interface.sql b/lib/registry/src/package/sql/queries/get_interface.sql deleted file mode 100644 index 8dffff7ece1..00000000000 --- a/lib/registry/src/package/sql/queries/get_interface.sql +++ /dev/null @@ -1,4 +0,0 @@ -SELECT content -FROM wasm_interfaces -WHERE interface_name = (?1) - AND version = (?2) diff --git a/lib/registry/src/package/sql/queries/insert_interface.sql b/lib/registry/src/package/sql/queries/insert_interface.sql deleted file mode 100644 index b1f99678ff4..00000000000 --- a/lib/registry/src/package/sql/queries/insert_interface.sql +++ /dev/null @@ -1,3 +0,0 @@ -INSERT INTO wasm_interfaces -(interface_name, version, date_added, content) -VALUES (?1, ?2, ?3, ?4) diff --git a/lib/registry/src/package/sql/queries/wasm_interface_existence_check.sql b/lib/registry/src/package/sql/queries/wasm_interface_existence_check.sql deleted file mode 100644 index d00f31e2d93..00000000000 --- a/lib/registry/src/package/sql/queries/wasm_interface_existence_check.sql +++ /dev/null @@ -1,5 +0,0 @@ -SELECT 1 -FROM wasm_interfaces -WHERE interface_name = (?1) - AND version = (?2) -LIMIT 1 diff --git a/lib/registry/src/publish.rs b/lib/registry/src/publish.rs deleted file mode 100644 index 570d3864ec4..00000000000 --- a/lib/registry/src/publish.rs +++ /dev/null @@ -1,621 +0,0 @@ -use crate::graphql::queries::get_signed_url::GetSignedUrlUrl; - -use crate::graphql::subscriptions::package_version_ready::PackageVersionState; -use crate::graphql::{ - mutations::{publish_package_mutation_chunked, PublishPackageMutationChunked}, - queries::{get_signed_url, GetSignedUrl}, -}; -use crate::subscriptions::subscribe_package_version_ready; -use crate::{format_graphql, WasmerConfig}; -use anyhow::{Context, Result}; -use console::{style, Emoji}; -use futures_util::StreamExt; -use graphql_client::GraphQLQuery; -use indicatif::{ProgressBar, ProgressState, ProgressStyle}; -use std::collections::BTreeMap; -use std::fmt::Write; -use std::io::Write as _; -use std::path::PathBuf; -use std::str::FromStr; -use std::sync::{Arc, Mutex}; -use std::time::Duration; -use tokio::io::AsyncBufReadExt; -use tokio::sync::oneshot::Receiver; -use wasmer_config::package::{NamedPackageIdent, PackageHash, PackageIdent}; - -static UPLOAD: Emoji<'_, '_> = Emoji("📤", ""); -static PACKAGE: Emoji<'_, '_> = Emoji("📦", ""); -static FIRE: Emoji<'_, '_> = Emoji("🔥", ""); - -/// Different conditions that can be "awaited" when publishing a package. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub struct PublishWait { - pub container: bool, - pub native_executables: bool, - pub bindings: bool, - - pub timeout: Option, -} - -impl PublishWait { - pub fn is_any(self) -> bool { - self.container || self.native_executables || self.bindings - } - - pub fn new_none() -> Self { - Self { - container: false, - native_executables: false, - bindings: false, - timeout: None, - } - } - - pub fn new_all() -> Self { - Self { - container: true, - native_executables: true, - bindings: true, - timeout: None, - } - } - - pub fn new_container() -> Self { - Self { - container: true, - native_executables: false, - bindings: false, - timeout: None, - } - } -} - -#[derive(Debug, Clone)] -pub enum SignArchiveResult { - Ok { - public_key_id: String, - signature: String, - }, - NoKeyRegistered, -} - -async fn wait_on(mut recv: Receiver<()>) { - loop { - _ = std::io::stdout().flush(); - if recv.try_recv().is_ok() { - println!("."); - break; - } else { - tokio::time::sleep(Duration::from_secs(1)).await; - print!("."); - } - } -} - -#[allow(clippy::too_many_arguments)] -pub async fn try_chunked_uploading( - registry: Option, - token: Option, - package: &Option, - manifest_string: &String, - license_file: &Option, - readme: &Option, - archive_name: &String, - archive_path: &PathBuf, - maybe_signature_data: &SignArchiveResult, - archived_data_size: u64, - quiet: bool, - wait: PublishWait, - timeout: Duration, - patch_namespace: Option, -) -> Result, anyhow::Error> { - let (registry, token) = initialize_registry_and_token(registry, token)?; - - let steps = if wait.is_any() { 3 } else { 2 }; - - let maybe_signature_data = sign_package(maybe_signature_data); - - // fetch this before showing the `Uploading...` message - // because there is a chance that the registry may not return a signed url. - // This usually happens if the package version already exists in the registry. - let signed_url = google_signed_url(®istry, &token, package, timeout)?; - - if !quiet { - println!( - "{} {} Uploading", - style(format!("[1/{steps}]")).bold().dim(), - UPLOAD - ); - } - - upload_package(&signed_url.url, archive_path, archived_data_size, timeout).await?; - - let name = package.as_ref().and_then(|p| p.name.clone()); - - let namespace = match patch_namespace { - Some(n) => Some(n), - None => package.as_ref().and_then(|p| { - p.name - .as_ref() - .map(|p| String::from(p.split_once('/').unwrap().0)) - }), - }; - - let q = - PublishPackageMutationChunked::build_query(publish_package_mutation_chunked::Variables { - name, - namespace, - version: package - .as_ref() - .and_then(|p| p.version.as_ref().map(|v| v.to_string())), - description: package.as_ref().and_then(|p| p.description.clone()), - manifest: manifest_string.to_string(), - license: package.as_ref().and_then(|p| p.license.clone()), - license_file: license_file.to_owned(), - readme: readme.to_owned(), - repository: package.as_ref().and_then(|p| p.repository.clone()), - homepage: package.as_ref().and_then(|p| p.homepage.clone()), - file_name: Some(archive_name.to_string()), - signature: maybe_signature_data, - signed_url: Some(signed_url.url), - private: Some(match package { - Some(p) => p.private, - None => true, - }), - wait: Some(wait.is_any()), - }); - - tracing::debug!("{:#?}", q); - - let (send, recv) = tokio::sync::oneshot::channel(); - let mut wait_t = None; - - if !quiet { - print!( - "{} {} Publishing package", - style(format!("[2/{steps}]")).bold().dim(), - PACKAGE - ); - - _ = std::io::stdout().flush(); - wait_t = Some(tokio::spawn(wait_on(recv))) - } - - let response: publish_package_mutation_chunked::ResponseData = { - let registry = registry.clone(); - let token = token.clone(); - tokio::spawn(async move { - crate::graphql::execute_query_with_timeout(®istry, &token, timeout, &q) - }) - .await?? - }; - - _ = send.send(()); - - if let Some(wait_t) = wait_t { - _ = wait_t.await; - }; - - tracing::debug!("{:#?}", response); - - if let Some(payload) = response.publish_package { - if !payload.success { - return Err(anyhow::anyhow!("Could not publish package")); - } else if let Some(pkg_version) = payload.package_version { - // Here we can assume that the package is *Some*. - let package = package.clone().unwrap(); - - if wait.is_any() { - wait_for_package_version_to_become_ready( - ®istry, - &token, - pkg_version.id, - quiet, - wait, - steps, - ) - .await?; - } - - let package_ident = PackageIdent::Named(NamedPackageIdent::from_str(&format!( - "{}@{}", - package - .name - .expect("Unnamed package was published as named"), - package - .version - .expect("Unversioned package was published as versioned") - ))?); - eprintln!("Package published successfully"); - // println!("🚀 Successfully published package `{}`", package_ident); - return Ok(Some(package_ident)); - } else if let Some(pkg_hash) = payload.package_webc { - let package_ident = PackageIdent::Hash( - PackageHash::from_str(&format!("sha256:{}", pkg_hash.webc_v3.unwrap().webc_sha256)) - .unwrap(), - ); - eprintln!("Package published successfully"); - // println!("🚀 Successfully published package `{}`", package_ident); - return Ok(Some(package_ident)); - } - - unreachable!(); - } else { - unreachable!(); - } -} - -fn initialize_registry_and_token( - registry: Option, - token: Option, -) -> Result<(String, String), anyhow::Error> { - let registry = match registry.as_ref() { - Some(s) => format_graphql(s), - None => { - let wasmer_dir = WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("{e}"))?; - - let config = WasmerConfig::from_file(&wasmer_dir); - - config - .map_err(|e| anyhow::anyhow!("{e}"))? - .registry - .get_current_registry() - } - }; - - let token = match token.as_ref() { - Some(s) => s.to_string(), - None => { - let wasmer_dir = WasmerConfig::get_wasmer_dir().map_err(|e| anyhow::anyhow!("{e}"))?; - - let config = WasmerConfig::from_file(&wasmer_dir); - - config - .map_err(|e| anyhow::anyhow!("{e}"))? - .registry - .get_login_token_for_registry(®istry) - .ok_or_else(|| { - anyhow::anyhow!("cannot publish package: not logged into registry {registry:?}") - })? - } - }; - - Ok((registry, token)) -} - -fn sign_package( - maybe_signature_data: &SignArchiveResult, -) -> Option { - match maybe_signature_data { - SignArchiveResult::Ok { - public_key_id, - signature, - } => { - log::info!( - "Package successfully signed with public key: \"{}\"!", - &public_key_id - ); - Some(publish_package_mutation_chunked::InputSignature { - public_key_key_id: public_key_id.to_string(), - data: signature.to_string(), - }) - } - SignArchiveResult::NoKeyRegistered => { - // TODO: uncomment this when we actually want users to start using it - //warn!("Publishing package without a verifying signature. Consider registering a key pair with wasmer"); - None - } - } -} - -fn google_signed_url( - registry: &str, - token: &str, - package: &Option, - timeout: Duration, -) -> Result { - let get_google_signed_url = GetSignedUrl::build_query(get_signed_url::Variables { - name: package - .as_ref() - .and_then(|p| p.name.as_ref().map(|n| n.to_string())), - version: package - .as_ref() - .and_then(|p| p.version.as_ref().map(|v| v.to_string())), - filename: match package { - Some(_) => None, - None => Some(format!("unnamed_package_{}", rand::random::())), - }, - expires_after_seconds: Some(60 * 30), - }); - - let _response: get_signed_url::ResponseData = crate::graphql::execute_query_with_timeout( - registry, - token, - timeout, - &get_google_signed_url, - )?; - - let url = _response.url.ok_or_else(|| match package { - Some(pkg) => { - anyhow::anyhow!( - "could not get signed url for package {:?}@{:?}", - pkg.name, - pkg.version - ) - } - None => { - anyhow::anyhow!("could not get signed url for unnamed package",) - } - })?; - Ok(url) -} - -async fn upload_package( - signed_url: &str, - archive_path: &PathBuf, - archived_data_size: u64, - timeout: Duration, -) -> Result<(), anyhow::Error> { - let url = url::Url::parse(signed_url).context("cannot parse signed url")?; - let client = reqwest::Client::builder() - .default_headers(reqwest::header::HeaderMap::default()) - .timeout(timeout) - .build() - .unwrap(); - - let res = client - .post(url) - .header(reqwest::header::CONTENT_LENGTH, "0") - .header(reqwest::header::CONTENT_TYPE, "application/octet-stream") - .header("x-goog-resumable", "start"); - - let result = res.send().await.unwrap(); - - if result.status() != reqwest::StatusCode::from_u16(201).unwrap() { - return Err(anyhow::anyhow!( - "Uploading package failed: got HTTP {:?} when uploading", - result.status() - )); - } - - let headers = result - .headers() - .into_iter() - .filter_map(|(k, v)| { - let k = k.to_string(); - let v = v.to_str().ok()?.to_string(); - Some((k.to_lowercase(), v)) - }) - .collect::>(); - - let session_uri = headers.get("location").unwrap().clone(); - - let total = archived_data_size; - - // archive_path - let mut file = tokio::fs::OpenOptions::new() - .read(true) - .open(archive_path) - .await - .map_err(|e| anyhow::anyhow!("cannot open archive {}: {e}", archive_path.display()))?; - - let pb = ProgressBar::new(archived_data_size); - pb.set_style(ProgressStyle::with_template("{spinner:.green} [{elapsed_precise}] [{wide_bar:.cyan/blue}] {bytes}/{total_bytes} ({eta})") - .unwrap() - .with_key("eta", |state: &ProgressState, w: &mut dyn Write| { - write!(w, "{:.1}s", state.eta().as_secs_f64()).unwrap() - }) - .progress_chars("#>-")); - - let chunk_size = 1_048_576; // 1MB - 315s / 100MB - let mut file_pointer = 0; - - let mut reader = tokio::io::BufReader::with_capacity(chunk_size, &mut file); - - let client = reqwest::Client::builder() - .default_headers(reqwest::header::HeaderMap::default()) - .build() - .unwrap(); - - while let Some(chunk) = reader.fill_buf().await.ok().map(|s| s.to_vec()) { - let n = chunk.len(); - - if chunk.is_empty() { - break; - } - - let start = file_pointer; - let end = file_pointer + chunk.len().saturating_sub(1); - let content_range = format!("bytes {start}-{end}/{total}"); - - let res = client - .put(&session_uri) - .header(reqwest::header::CONTENT_TYPE, "application/octet-stream") - .header(reqwest::header::CONTENT_LENGTH, format!("{}", chunk.len())) - .header("Content-Range".to_string(), content_range) - .body(chunk.to_vec()); - - pb.set_position(file_pointer as u64); - - res.send() - .await - .map(|response| response.error_for_status()) - .map_err(|e| { - anyhow::anyhow!( - "cannot send request to {session_uri} (chunk {}..{}): {e}", - file_pointer, - file_pointer + chunk_size - ) - })??; - - if n < chunk_size { - break; - } - - reader.consume(n); - file_pointer += n; - } - - pb.finish_and_clear(); - Ok(()) -} - -struct PackageVersionReadySharedState { - webc_generated: Arc>>, - bindings_generated: Arc>>, - native_exes_generated: Arc>>, -} - -impl PackageVersionReadySharedState { - fn new() -> Self { - Self { - webc_generated: Arc::new(Mutex::new(Option::None)), - bindings_generated: Arc::new(Mutex::new(Option::None)), - native_exes_generated: Arc::new(Mutex::new(Option::None)), - } - } -} - -// fn create_spinner(m: &MultiProgress, message: String) -> ProgressBar { -// let spinner = m.add(ProgressBar::new_spinner()); -// spinner.set_message(message); -// spinner.set_style(ProgressStyle::default_spinner()); -// spinner.enable_steady_tick(Duration::from_millis(100)); -// spinner -// } -// -// fn show_spinners_while_waiting(state: &PackageVersionReadySharedState) { -// // Clone shared state for threads -// let (state_webc, state_bindings, state_native) = ( -// Arc::clone(&state.webc_generated), -// Arc::clone(&state.bindings_generated), -// Arc::clone(&state.native_exes_generated), -// ); -// let m = MultiProgress::new(); -// -// let webc_spinner = create_spinner(&m, String::from("Generating package...")); -// let bindings_spinner = create_spinner(&m, String::from("Generating language bindings...")); -// let exe_spinner = create_spinner(&m, String::from("Generating native executables...")); -// -// let check_and_finish = |spinner: ProgressBar, state: Arc>>, name: String| { -// thread::spawn(move || loop { -// match state.lock() { -// Ok(lock) => { -// if lock.is_some() { -// // spinner.finish_with_message(format!("✅ {} generation complete", name)); -// spinner.finish_and_clear(); -// break; -// } -// } -// Err(_) => { -// break; -// } -// } -// thread::sleep(Duration::from_millis(100)); -// }); -// }; -// check_and_finish(webc_spinner, state_webc, String::from("package")); -// check_and_finish( -// bindings_spinner, -// state_bindings, -// String::from("Language bindings"), -// ); -// check_and_finish( -// exe_spinner, -// state_native, -// String::from("Native executables"), -// ); -// } - -async fn wait_for_package_version_to_become_ready( - registry: &str, - token: &str, - package_version_id: impl AsRef, - quiet: bool, - mut conditions: PublishWait, - steps: usize, -) -> Result<()> { - let (mut stream, _client) = - subscribe_package_version_ready(registry, token, package_version_id.as_ref()).await?; - - let state = PackageVersionReadySharedState::new(); - - let (send, recv) = tokio::sync::oneshot::channel(); - let mut wait_t = None; - - if !quiet { - print!( - "{} {} Waiting for package to be available", - style(format!("[3/{steps}]")).bold().dim(), - FIRE - ); - _ = std::io::stdout().flush(); - wait_t = Some(tokio::spawn(wait_on(recv))); - } - - if !conditions.is_any() { - return Ok(()); - } - - let deadline = conditions - .timeout - .map(|x| std::time::Instant::now() + x) - .unwrap_or_else(|| std::time::Instant::now() + std::time::Duration::from_secs(60 * 10)); - - loop { - if !conditions.is_any() { - break; - } - if std::time::Instant::now() > deadline { - _ = send.send(()); - return Err(anyhow::anyhow!( - "Timed out waiting for package version to become ready" - )); - } - - let data = match tokio::time::timeout_at(deadline.into(), stream.next()).await { - Err(_) => { - _ = send.send(()); - return Err(anyhow::anyhow!( - "Timed out waiting for package version to become ready" - )); - } - Ok(None) => { - break; - } - Ok(Some(data)) => data, - }; - - if let Some(res_data) = data.unwrap().data { - match res_data.package_version_ready.state { - PackageVersionState::BINDINGS_GENERATED => { - let mut st = state.bindings_generated.lock().unwrap(); - let is_ready = res_data.package_version_ready.success; - *st = Some(is_ready); - conditions.bindings = false; - } - PackageVersionState::NATIVE_EXES_GENERATED => { - let mut st = state.native_exes_generated.lock().unwrap(); - *st = Some(res_data.package_version_ready.success); - - conditions.native_executables = false; - } - PackageVersionState::WEBC_GENERATED => { - let mut st = state.webc_generated.lock().unwrap(); - *st = Some(res_data.package_version_ready.success); - - conditions.container = false; - } - PackageVersionState::Other(_) => {} - } - } - } - - _ = send.send(()); - - if let Some(wait_t) = wait_t { - _ = wait_t.await; - } - - Ok(()) -} diff --git a/lib/registry/src/subscriptions.rs b/lib/registry/src/subscriptions.rs deleted file mode 100644 index daca2295e5a..00000000000 --- a/lib/registry/src/subscriptions.rs +++ /dev/null @@ -1,77 +0,0 @@ -use std::{env, future::IntoFuture}; - -use anyhow::Context; - -use crate::graphql::subscriptions::{package_version_ready, PackageVersionReady}; - -use graphql_client::GraphQLQuery; -use graphql_ws_client::{graphql::StreamingOperation, Client, Subscription}; - -use tokio_tungstenite::tungstenite::{client::IntoClientRequest, http::HeaderValue}; - -pub use crate::graphql::subscriptions::package_version_ready::PackageVersionState; - -async fn subscribe_graphql( - registry_url: &str, - login_token: &str, - variables: Q::Variables, -) -> anyhow::Result<(Subscription>, Client)> -where - ::Variables: Send + Sync + Unpin, -{ - let mut url = url::Url::parse(registry_url).unwrap(); - if url.scheme() == "http" { - url.set_scheme("ws").unwrap(); - } else if url.scheme() == "https" { - url.set_scheme("wss").unwrap(); - } - - let mut req = url.into_client_request()?; - req.headers_mut().insert( - "Sec-WebSocket-Protocol", - HeaderValue::from_str("graphql-transport-ws")?, - ); - let token = env::var("WASMER_TOKEN") - .ok() - .or_else(|| env::var("WAPM_REGISTRY_TOKEN").ok()) - .unwrap_or_else(|| login_token.to_string()); - req.headers_mut().insert( - reqwest::header::AUTHORIZATION, - HeaderValue::from_str(&format!("Bearer {}", token))?, - ); - let user_agent = crate::client::RegistryClient::default_user_agent(); - req.headers_mut().insert( - reqwest::header::USER_AGENT, - HeaderValue::from_str(&user_agent)?, - ); - let (connection, _resp) = async_tungstenite::tokio::connect_async(req) - .await - .context("could not connect")?; - - let (client, actor) = graphql_ws_client::Client::build(connection).await?; - tokio::spawn(actor.into_future()); - - let stream = client - .subscribe(StreamingOperation::::new(variables)) - .await?; - - Ok((stream, client)) -} - -pub async fn subscribe_package_version_ready( - registry_url: &str, - login_token: &str, - package_version_id: &str, -) -> anyhow::Result<( - Subscription>, - Client, -)> { - subscribe_graphql( - registry_url, - login_token, - package_version_ready::Variables { - package_version_id: package_version_id.to_string(), - }, - ) - .await -} diff --git a/lib/registry/src/types.rs b/lib/registry/src/types.rs deleted file mode 100644 index 3db9a2bf8c5..00000000000 --- a/lib/registry/src/types.rs +++ /dev/null @@ -1,31 +0,0 @@ -/// Payload for publishing a new Deploy app. -#[derive(Clone, Debug)] -pub struct PublishDeployAppRawVars { - /// Name for the app. - /// If not specified a random name will be generated. - pub name: Option, - - /// The namespace to deploy the app to. - /// - /// If not specified the app will be deployed under the current users - /// namespace. - pub namespace: Option, - - /// The raw DeployV1 configuration. - pub config: serde_json::Value, -} - -/// Data for a deployed app. -#[derive(Clone, Debug)] -pub struct PublishDeployAppOutput { - pub app_id: String, - pub app_name: String, - pub version_id: String, - pub version_name: String, - pub owner_name: String, -} - -#[derive(Clone, Debug)] -pub struct NewNonceOutput { - pub auth_url: String, -} diff --git a/lib/registry/src/utils.rs b/lib/registry/src/utils.rs deleted file mode 100644 index a45ed237b6c..00000000000 --- a/lib/registry/src/utils.rs +++ /dev/null @@ -1,21 +0,0 @@ -use crate::graphql::{ - execute_query, - queries::{who_am_i_query, WhoAmIQuery}, -}; -use graphql_client::GraphQLQuery; - -pub fn get_username(registry: &str) -> anyhow::Result> { - let q = WhoAmIQuery::build_query(who_am_i_query::Variables {}); - let response: who_am_i_query::ResponseData = execute_query(registry, "", &q)?; - Ok(response.viewer.map(|viewer| viewer.username)) -} - -pub fn get_username_registry_token(registry: &str, token: &str) -> anyhow::Result> { - let q = WhoAmIQuery::build_query(who_am_i_query::Variables {}); - let response: who_am_i_query::ResponseData = execute_query(registry, token, &q)?; - Ok(response.viewer.map(|viewer| viewer.username)) -} - -pub fn normalize_path(s: &str) -> String { - s.strip_prefix(r"\\?\").unwrap_or(s).to_string() -} diff --git a/lib/registry/src/wasmer_env.rs b/lib/registry/src/wasmer_env.rs deleted file mode 100644 index dbcc267a717..00000000000 --- a/lib/registry/src/wasmer_env.rs +++ /dev/null @@ -1,295 +0,0 @@ -use std::path::{Path, PathBuf}; - -use crate::WasmerConfig; -use anyhow::{Context, Error}; -use url::Url; - -/// Command-line flags for determining the local "Wasmer Environment". -/// -/// This is where you access `$WASMER_DIR`, the `$WASMER_DIR/wasmer.toml` config -/// file, and specify the current registry. -#[derive(Debug, Clone, PartialEq)] -#[cfg_attr(feature = "clap", derive(clap::Parser))] -pub struct WasmerEnv { - /// Set Wasmer's home directory - #[cfg_attr(feature = "clap", clap(long, env = "WASMER_DIR", default_value = WASMER_DIR.as_os_str()))] - wasmer_dir: PathBuf, - /// The registry to fetch packages from (inferred from the environment by - /// default) - #[cfg_attr(feature = "clap", clap(long, env = "WASMER_REGISTRY"))] - registry: Option, - /// The directory cached artefacts are saved to. - #[cfg_attr(feature = "clap", clap(long, env = "WASMER_CACHE_DIR"))] - cache_dir: Option, - /// The API token to use when communicating with the registry (inferred from - /// the environment by default) - #[cfg_attr(feature = "clap", clap(long, env = "WASMER_TOKEN"))] - token: Option, -} - -impl WasmerEnv { - pub fn new( - wasmer_dir: PathBuf, - registry: Option, - token: Option, - cache_dir: Option, - ) -> Self { - WasmerEnv { - wasmer_dir, - registry, - token, - cache_dir, - } - } - - pub fn registry_public_url(&self) -> Result { - let mut url = self.registry_endpoint()?; - url.set_path(""); - - let mut domain = url.host_str().context("url has no host")?.to_string(); - if domain.starts_with("registry.") { - domain = domain.strip_prefix("registry.").unwrap().to_string(); - } - url.set_host(Some(&domain)) - .context("could not derive registry public url")?; - - Ok(url) - } - - /// Get the GraphQL endpoint used to query the registry. - pub fn registry_endpoint(&self) -> Result { - if let Some(registry) = &self.registry { - return registry.graphql_endpoint(); - } - - let config = self.config()?; - let url = config.registry.get_current_registry().parse()?; - - Ok(url) - } - - /// Load the current Wasmer config. - pub fn config(&self) -> Result { - WasmerConfig::from_file(self.dir()) - .map_err(Error::msg) - .with_context(|| { - format!( - "Unable to load the config from the \"{}\" directory", - self.dir().display() - ) - }) - } - - /// The directory all Wasmer artifacts are stored in. - pub fn dir(&self) -> &Path { - &self.wasmer_dir - } - - /// The directory all cached artifacts should be saved to. - pub fn cache_dir(&self) -> PathBuf { - match &self.cache_dir { - Some(cache_dir) => cache_dir.clone(), - None => self.dir().join("cache"), - } - } - - /// Retrieve the specified token. - /// - /// NOTE: In contrast to [`Self::token`], this will not fall back to loading - /// the token from the confg file. - pub fn get_token_opt(&self) -> Option<&str> { - self.token.as_deref() - } - - /// The API token for the active registry. - pub fn token(&self) -> Option { - if let Some(token) = &self.token { - return Some(token.clone()); - } - - // Fall back to the config file - - let config = self.config().ok()?; - let registry_endpoint = self.registry_endpoint().ok()?; - config - .registry - .get_login_token_for_registry(registry_endpoint.as_str()) - } -} - -impl Default for WasmerEnv { - fn default() -> Self { - Self { - wasmer_dir: WASMER_DIR.clone(), - registry: None, - token: None, - cache_dir: None, - } - } -} - -lazy_static::lazy_static! { - /// The default value for `$WASMER_DIR`. - pub static ref WASMER_DIR: PathBuf = match crate::WasmerConfig::get_wasmer_dir() { - Ok(path) => path, - Err(e) => { - if let Some(install_prefix) = option_env!("WASMER_INSTALL_PREFIX") { - return PathBuf::from(install_prefix); - } - - panic!("Unable to determine the wasmer dir: {e}"); - } - }; -} - -/// A registry as specified by the user. -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct Registry(String); - -impl Registry { - /// Get the [`Registry`]'s string representation. - pub fn as_str(&self) -> &str { - self.0.as_str() - } - - /// Get the GraphQL endpoint for this [`Registry`]. - pub fn graphql_endpoint(&self) -> Result { - let url = crate::format_graphql(self.as_str()).parse()?; - Ok(url) - } -} - -impl From for Registry { - fn from(value: String) -> Self { - Registry(value) - } -} - -impl From<&str> for Registry { - fn from(value: &str) -> Self { - Registry(value.to_string()) - } -} - -#[cfg(test)] -mod tests { - use tempfile::TempDir; - - use super::*; - - const WASMER_TOML: &str = r#" - telemetry_enabled = false - update_notifications_enabled = false - - [registry] - active_registry = "https://registry.wasmer.io/graphql" - - [[registry.tokens]] - registry = "https://registry.wasmer.wtf/graphql" - token = "dev-token" - - [[registry.tokens]] - registry = "https://registry.wasmer.io/graphql" - token = "prod-token" - "#; - - #[test] - fn load_defaults_from_config() { - let temp = TempDir::new().unwrap(); - std::fs::write(temp.path().join("wasmer.toml"), WASMER_TOML).unwrap(); - - let env = WasmerEnv { - wasmer_dir: temp.path().to_path_buf(), - registry: None, - cache_dir: None, - token: None, - }; - - assert_eq!( - env.registry_endpoint().unwrap().as_str(), - "https://registry.wasmer.io/graphql" - ); - assert_eq!(env.token().unwrap(), "prod-token"); - assert_eq!(env.cache_dir(), temp.path().join("cache")); - } - - #[test] - fn override_token() { - let temp = TempDir::new().unwrap(); - std::fs::write(temp.path().join("wasmer.toml"), WASMER_TOML).unwrap(); - - let env = WasmerEnv { - wasmer_dir: temp.path().to_path_buf(), - registry: None, - cache_dir: None, - token: Some("asdf".to_string()), - }; - - assert_eq!( - env.registry_endpoint().unwrap().as_str(), - "https://registry.wasmer.io/graphql" - ); - assert_eq!(env.token().unwrap(), "asdf"); - assert_eq!(env.cache_dir(), temp.path().join("cache")); - } - - #[test] - fn override_registry() { - let temp = TempDir::new().unwrap(); - std::fs::write(temp.path().join("wasmer.toml"), WASMER_TOML).unwrap(); - let env = WasmerEnv { - wasmer_dir: temp.path().to_path_buf(), - registry: Some(Registry::from("wasmer.wtf")), - cache_dir: None, - token: None, - }; - - assert_eq!( - env.registry_endpoint().unwrap().as_str(), - "https://registry.wasmer.wtf/graphql" - ); - assert_eq!(env.token().unwrap(), "dev-token"); - assert_eq!(env.cache_dir(), temp.path().join("cache")); - } - - #[test] - fn override_registry_and_token() { - let temp = TempDir::new().unwrap(); - std::fs::write(temp.path().join("wasmer.toml"), WASMER_TOML).unwrap(); - - let env = WasmerEnv { - wasmer_dir: temp.path().to_path_buf(), - registry: Some(Registry::from("wasmer.wtf")), - cache_dir: None, - token: Some("asdf".to_string()), - }; - - assert_eq!( - env.registry_endpoint().unwrap().as_str(), - "https://registry.wasmer.wtf/graphql" - ); - assert_eq!(env.token().unwrap(), "asdf"); - assert_eq!(env.cache_dir(), temp.path().join("cache")); - } - - #[test] - fn override_cache_dir() { - let temp = TempDir::new().unwrap(); - std::fs::write(temp.path().join("wasmer.toml"), WASMER_TOML).unwrap(); - let expected_cache_dir = temp.path().join("some-other-cache"); - - let env = WasmerEnv { - wasmer_dir: temp.path().to_path_buf(), - registry: None, - cache_dir: Some(expected_cache_dir.clone()), - token: None, - }; - - assert_eq!( - env.registry_endpoint().unwrap().as_str(), - "https://registry.wasmer.io/graphql" - ); - assert_eq!(env.token().unwrap(), "prod-token"); - assert_eq!(env.cache_dir(), expected_cache_dir); - } -} diff --git a/lib/virtual-net/Cargo.toml b/lib/virtual-net/Cargo.toml index d4bdd69448e..6fab8e1a62b 100644 --- a/lib/virtual-net/Cargo.toml +++ b/lib/virtual-net/Cargo.toml @@ -29,7 +29,7 @@ serde = { version = "1.0", default-features = false, features = ["derive"] } pin-project-lite = "0.2.9" futures-util = { workspace = true } anyhow = "1.0" -tokio-serde = { version = "0.8", features = ["bincode"], optional = true } +tokio-serde = { version = "0.9", features = ["bincode"], optional = true } tokio-util = { version = "0.7.8", features = ["codec"], optional = true } hyper-tungstenite = { version = "0.13", optional = true } tokio-tungstenite = { version = "0.21", optional = true } diff --git a/lib/wasi-types/Cargo.toml b/lib/wasi-types/Cargo.toml index 99413a1c9db..4809202c2dc 100644 --- a/lib/wasi-types/Cargo.toml +++ b/lib/wasi-types/Cargo.toml @@ -29,7 +29,7 @@ bitflags = "1.3.0" cfg-if = "1.0.0" anyhow = "1.0.66" byteorder = "1.3" -time = { version = "0.3", features = ["formatting"] } +time = { workspace = true, features = ["formatting"] } tracing = { version = "0.1.37" } [dev-dependencies.pretty_assertions] diff --git a/lib/wasix/Cargo.toml b/lib/wasix/Cargo.toml index 1773054d3c4..eb02d6ac96d 100644 --- a/lib/wasix/Cargo.toml +++ b/lib/wasix/Cargo.toml @@ -14,12 +14,21 @@ rust-version.workspace = true [dependencies] wasmer-package.workspace = true -wasmer-wasix-types = { path = "../wasi-types", version = "0.29.0", features = [ "enable-serde" ] } +wasmer-wasix-types = { path = "../wasi-types", version = "0.29.0", features = [ + "enable-serde", +] } wasmer-types = { path = "../types", version = "=5.0.0-rc.1", default-features = false } -wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = ["wat", "js-serializable-module"] } -virtual-mio = { path = "../virtual-io", version = "0.5.0", default-features = false } -virtual-fs = { path = "../virtual-fs", version = "0.18.0", default-features = false, features = ["webc-fs"] } -virtual-net = { path = "../virtual-net", version = "0.10.0", default-features = false, features = ["rkyv"] } +wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = [ + "wat", + "js-serializable-module", +] } +virtual-mio = { path = "../virtual-io", version = "0.5.0", default-features = false } +virtual-fs = { path = "../virtual-fs", version = "0.18.0", default-features = false, features = [ + "webc-fs", +] } +virtual-net = { path = "../virtual-net", version = "0.10.0", default-features = false, features = [ + "rkyv", +] } wasmer-journal = { path = "../journal", version = "0.11.0", default-features = false } wasmer-emscripten = { path = "../emscripten", version = "=5.0.0-rc.1", optional = true } wasmer-config = { version = "0.9.0", path = "../config" } @@ -42,7 +51,7 @@ getrandom = "0.2" typetag = { version = "0.1", optional = true } serde = { version = "1.0", default-features = false, features = ["derive"] } bincode = { version = "1.3" } -chrono = { version = "^0.4.31", default-features = false, features = [ +chrono = { version = "^0.4.38", default-features = false, features = [ "wasmbind", "std", "clock", @@ -144,8 +153,15 @@ windows-sys = { version = "0.59", features = [ terminal_size = { version = "0.3.0" } [dev-dependencies] -wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = ["wat", "js-serializable-module"] } -tokio = { workspace = true, features = [ "sync", "macros", "rt" ], default-features = false } +wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = [ + "wat", + "js-serializable-module", +] } +tokio = { workspace = true, features = [ + "sync", + "macros", + "rt", +], default-features = false } pretty_assertions.workspace = true tracing-test = "0.2.4" wasm-bindgen-test = "0.3.0" @@ -156,7 +172,11 @@ tracing-wasm = "0.2" [target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies] tracing-subscriber = { version = "^0.3" } -wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = ["wat", "js-serializable-module", "cranelift"] } +wasmer = { path = "../api", version = "=5.0.0-rc.1", default-features = false, features = [ + "wat", + "js-serializable-module", + "cranelift", +] } [features] default = ["sys-default"] diff --git a/lib/wasm-interface/Cargo.toml b/lib/wasm-interface/Cargo.toml deleted file mode 100644 index c071307414d..00000000000 --- a/lib/wasm-interface/Cargo.toml +++ /dev/null @@ -1,29 +0,0 @@ -[package] -name = "wasmer-wasm-interface" -description = "WASM Interface definition and parser" -readme = "README.md" -authors.workspace = true -edition.workspace = true -homepage.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true -version.workspace = true - -[dependencies] -bincode = { version = "1", optional = true } -either = "1.5" -nom = "5" -serde = { version = "1", features = ["derive"] } -wasmparser = { workspace = true, optional = true } - -[dev-dependencies] -wat = "1.0" - -[features] -validation = ["wasmparser"] -binary_encode = ["bincode"] -default = ["validation"] - -[package.metadata.docs.rs] -rustc-args = ["--cfg", "docsrs"] diff --git a/lib/wasm-interface/README.md b/lib/wasm-interface/README.md deleted file mode 100644 index c3526b64310..00000000000 --- a/lib/wasm-interface/README.md +++ /dev/null @@ -1,88 +0,0 @@ -# Wasm Interface - -This is an experimental crate for validating the imports and exports of a WebAssembly module. - -For the time being, Wasm Interface provides: - -- a convenient text format for specifying the requirements of Wasm modules -- a convenient way to compose interfaces safely (it ensures no conflicts (duplicates are allowed but they must agree)) -- validation that the modules meet the requirements - -## Syntax example - -Here's the interface for the current version of [WASI](https://github.com/WebAssembly/WASI): - -```lisp -(interface "wasi_unstable" - ;; Here's a bunch of function imports! - (func (import "wasi_unstable" "args_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "args_sizes_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "clock_res_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "clock_time_get") (param i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "environ_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "environ_sizes_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_advise") (param i32 i64 i64 i32) (result i32)) - (func (import "wasi_unstable" "fd_allocate") (param i32 i64 i64) (result i32)) - (func (import "wasi_unstable" "fd_close") (param i32) (result i32)) - (func (import "wasi_unstable" "fd_datasync") (param i32) (result i32)) - (func (import "wasi_unstable" "fd_fdstat_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_fdstat_set_flags") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_fdstat_set_rights") (param i32 i64 i64) (result i32)) - (func (import "wasi_unstable" "fd_filestat_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_filestat_set_size") (param i32 i64) (result i32)) - (func (import "wasi_unstable" "fd_filestat_set_times") (param i32 i64 i64 i32) (result i32)) - (func (import "wasi_unstable" "fd_pread") (param i32 i32 i32 i64 i32) (result i32)) - (func (import "wasi_unstable" "fd_prestat_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_prestat_dir_name") (param i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_pwrite") (param i32 i32 i32 i64 i32) (result i32)) - (func (import "wasi_unstable" "fd_read") (param i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_readdir") (param i32 i32 i32 i64 i32) (result i32)) - (func (import "wasi_unstable" "fd_renumber") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_seek") (param i32 i64 i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_sync") (param i32) (result i32)) - (func (import "wasi_unstable" "fd_tell") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "fd_write") (param i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_create_directory") (param i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_filestat_get") (param i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_filestat_set_times") (param i32 i32 i32 i32 i64 i64 i32) (result i32)) - (func (import "wasi_unstable" "path_link") (param i32 i32 i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_open") (param i32 i32 i32 i32 i32 i64 i64 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_readlink") (param i32 i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_remove_directory") (param i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_rename") (param i32 i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_symlink") (param i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "path_unlink_file") (param i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "poll_oneoff") (param i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "proc_exit") (param i32)) - (func (import "wasi_unstable" "proc_raise") (param i32) (result i32)) - (func (import "wasi_unstable" "random_get") (param i32 i32) (result i32)) - (func (import "wasi_unstable" "sched_yield") (result i32)) - (func (import "wasi_unstable" "sock_recv") (param i32 i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "sock_send") (param i32 i32 i32 i32 i32) (result i32)) - (func (import "wasi_unstable" "sock_shutdown") (param i32 i32) (result i32)) -) -``` - - -Notes: -- multiple `assert-import` and `assert-export` declarations are allowed. -- comments (starts with `;` and ends with a newline) and whitespace are valid between any tokens - -## Semantics - -All imports used by the module must be specified in the interface. - -All exports in the interface must be exported by the module. - -Thus the module may have additional exports than the interface or fewer imports than the interface specifies and be considered valid. - - -## Misc - -Wasm Interface serves a slightly different purpose than the proposed WebIDL for Wasm standard, but may be replaced by it in the future if things change. - -Due to an issue with nested closures in Rust, `wasm-interface` can't both compile on stable and have good error reporting. This is being fixed and `wasm-interface` will be updated to have better error handling. - -See the `parser.rs` file for a comment containing the grammar in a BNF style. - -Suggestions, contributions, and thoughts welcome! This is an experiment in the early stages, but we hope to work with the wider community and develop this in cooperation with all interested parties. diff --git a/lib/wasm-interface/src/interface.rs b/lib/wasm-interface/src/interface.rs deleted file mode 100644 index 12a4d1f7554..00000000000 --- a/lib/wasm-interface/src/interface.rs +++ /dev/null @@ -1,205 +0,0 @@ -//! The definition of a WASM interface - -use crate::interface_matcher::InterfaceMatcher; -use serde::{Deserialize, Serialize}; -use std::collections::{hash_map::Entry, HashMap, HashSet}; - -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] -pub struct Interface { - /// The name the interface gave itself - pub name: Option, - /// Things that the module can import - pub imports: HashMap<(String, String), Import>, - /// Things that the module must export - pub exports: HashMap, -} - -impl Interface { - pub fn merge(&self, other: Interface) -> Result { - let mut base = self.clone(); - - for (key, val) in other.imports { - match base.imports.entry(key) { - Entry::Occupied(e) if *e.get() != val => { - let (namespace, name) = e.key(); - let original_value = e.get(); - return Err(format!("Conflict detected: the import \"{namespace}\" \"{name}\" was found but the definitions were different: {original_value:?} {val:?}")); - } - Entry::Occupied(_) => { - // it's okay for the imported items to be the same. - } - Entry::Vacant(e) => { - e.insert(val); - } - }; - } - - for (key, val) in other.exports { - match base.exports.entry(key) { - Entry::Occupied(e) if *e.get() != val => { - let name = e.key(); - let original_value = e.get(); - return Err(format!("Conflict detected: the key \"{name}\" was found in exports but the definitions were different: {original_value:?} {val:?}")); - } - Entry::Occupied(_) => { - // it's okay for the exported items to be the same. - } - Entry::Vacant(e) => { - e.insert(val); - } - }; - } - - Ok(base) - } - - pub fn create_interface_matcher(&self) -> InterfaceMatcher { - let mut namespaces = HashSet::new(); - let mut namespace_imports: HashMap> = - HashMap::with_capacity(self.imports.len()); - let mut exports = HashSet::with_capacity(self.exports.len()); - - for (_, import) in self.imports.iter() { - match import { - Import::Func { namespace, .. } | Import::Global { namespace, .. } => { - if !namespaces.contains(namespace) { - namespaces.insert(namespace.clone()); - } - let ni = namespace_imports.entry(namespace.clone()).or_default(); - ni.insert(import.clone()); - } - } - } - for (_, export) in self.exports.iter() { - exports.insert(export.clone()); - } - InterfaceMatcher { - namespaces, - namespace_imports, - exports, - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Import { - Func { - namespace: String, - name: String, - params: Vec, - result: Vec, - }, - Global { - namespace: String, - name: String, - var_type: WasmType, - }, -} - -impl Import { - pub fn format_key(ns: &str, name: &str) -> (String, String) { - (ns.to_string(), name.to_string()) - } - - /// Get the key used to look this import up in the Interface's import hashmap - pub fn get_key(&self) -> (String, String) { - match self { - Import::Func { - namespace, name, .. - } - | Import::Global { - namespace, name, .. - } => Self::format_key(namespace, name), - } - } -} - -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum Export { - Func { - name: String, - params: Vec, - result: Vec, - }, - Global { - name: String, - var_type: WasmType, - }, -} - -impl Export { - pub fn format_key(name: &str) -> String { - name.to_string() - } - - /// Get the key used to look this export up in the Interface's export hashmap - pub fn get_key(&self) -> String { - match self { - Export::Func { name, .. } | Export::Global { name, .. } => Self::format_key(name), - } - } -} - -/// Primitive wasm type -#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)] -pub enum WasmType { - I32, - I64, - F32, - F64, -} - -impl std::fmt::Display for WasmType { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - write!( - f, - "{}", - match self { - WasmType::I32 => "i32", - WasmType::I64 => "i64", - WasmType::F32 => "f32", - WasmType::F64 => "f64", - } - ) - } -} - -#[cfg(test)] -mod test { - use crate::parser; - - #[test] - fn merging_works() { - let interface1_src = - r#"(interface (func (import "env" "plus_one") (param i32) (result i32)))"#; - let interface2_src = - r#"(interface (func (import "env" "plus_one") (param i64) (result i64)))"#; - let interface3_src = - r#"(interface (func (import "env" "times_two") (param i64) (result i64)))"#; - let interface4_src = - r#"(interface (func (import "env" "times_two") (param i64 i64) (result i64)))"#; - let interface5_src = r#"(interface (func (export "empty_bank_account") (param) (result)))"#; - let interface6_src = - r#"(interface (func (export "empty_bank_account") (param) (result i64)))"#; - - let interface1 = parser::parse_interface(interface1_src).unwrap(); - let interface2 = parser::parse_interface(interface2_src).unwrap(); - let interface3 = parser::parse_interface(interface3_src).unwrap(); - let interface4 = parser::parse_interface(interface4_src).unwrap(); - let interface5 = parser::parse_interface(interface5_src).unwrap(); - let interface6 = parser::parse_interface(interface6_src).unwrap(); - - assert!(interface1.merge(interface2.clone()).is_err()); - assert!(interface2.merge(interface1.clone()).is_err()); - assert!(interface1.merge(interface3.clone()).is_ok()); - assert!(interface2.merge(interface3.clone()).is_ok()); - assert!(interface3.merge(interface2).is_ok()); - assert!( - interface1.merge(interface1.clone()).is_ok(), - "exact matches are accepted" - ); - assert!(interface3.merge(interface4).is_err()); - assert!(interface5.merge(interface5.clone()).is_ok()); - assert!(interface5.merge(interface6).is_err()); - } -} diff --git a/lib/wasm-interface/src/interface_matcher.rs b/lib/wasm-interface/src/interface_matcher.rs deleted file mode 100644 index c9bf62b06fc..00000000000 --- a/lib/wasm-interface/src/interface_matcher.rs +++ /dev/null @@ -1,29 +0,0 @@ -use serde::{Deserialize, Serialize}; -use std::collections::{HashMap, HashSet}; - -use crate::interface::{Export, Import}; - -/// A struct containing data for more efficient matching. -/// -/// An ideal use case for this is to parse [`Interface`]s at compile time, -/// create [`InterfaceMatcher`]s, and store them as bytes so that they -/// can be efficiently loaded at runtime for matching. -#[derive(Debug, Clone, PartialEq, Eq, Default, Serialize, Deserialize)] -pub struct InterfaceMatcher { - pub namespaces: HashSet, - pub namespace_imports: HashMap>, - pub exports: HashSet, -} - -#[cfg(feature = "binary_encode")] -impl InterfaceMatcher { - /// Store the matcher as bytes to avoid reparsing - fn into_bytes(&self) -> Vec { - bincode::serialize(self).expect("Could not serialize InterfaceMatcher") - } - - /// Load the matcher from bytes to avoid reparsing - fn from_bytes(bytes: &[u8]) -> Option { - bincode::deserialize(bytes).ok() - } -} diff --git a/lib/wasm-interface/src/lib.rs b/lib/wasm-interface/src/lib.rs deleted file mode 100644 index 9dea4482b38..00000000000 --- a/lib/wasm-interface/src/lib.rs +++ /dev/null @@ -1,14 +0,0 @@ -#![type_length_limit = "5795522"] -//! Definition and parsing of wasm interfaces -//! -//! wasm interfaces ensure wasm modules conform to a specific shape -//! they do this by asserting on the imports and exports of the module. -#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))] - -pub mod interface; -pub mod interface_matcher; -pub mod parser; -#[cfg(feature = "validation")] -pub mod validate; - -pub use interface::*; diff --git a/lib/wasm-interface/src/parser.rs b/lib/wasm-interface/src/parser.rs deleted file mode 100644 index 320a433504c..00000000000 --- a/lib/wasm-interface/src/parser.rs +++ /dev/null @@ -1,596 +0,0 @@ -//! Parsers to get a wasm interface from text -//! -//! The grammar of the text format is: -//! interface = "(" interface name? interface-entry* ")" -//! interface-entry = func | global -//! -//! func = import-fn | export-fn -//! global = import-global | export-global -//! -//! import-fn = "(" "func" import-id param-list? result-list? ")" -//! import-global = "(" "global" import-id type-decl ")" -//! import-id = "(" "import" namespace name ")" -//! -//! export-fn = "(" "func" export-id param-list? result-list? ")" -//! export-global = "(" "global" export-id type-decl ")" -//! export-id = "(" export name ")" -//! -//! param-list = "(" param type* ")" -//! result-list = "(" result type* ")" -//! type-decl = "(" "type" type ")" -//! namespace = "\"" identifier "\"" -//! name = "\"" identifier "\"" -//! identifier = any character that's not a whitespace character or an open or close parenthesis -//! type = "i32" | "i64" | "f32" | "f64" -//! -//! `+` means 1 or more -//! `*` means 0 or more -//! `?` means 0 or 1 -//! `|` means "or" -//! `\"` means one `"` character -//! -//! comments start with a `;` character and go until a newline `\n` character is reached -//! comments and whitespace are valid between any tokens - -use either::Either; -use nom::{ - branch::*, - bytes::complete::{escaped, is_not, tag}, - character::complete::{char, multispace0, multispace1, one_of}, - combinator::*, - error::context, - multi::many0, - sequence::{delimited, preceded, tuple}, - IResult, -}; - -use crate::interface::*; - -/// Some example input: -/// (interface "example_interface" -/// (func (import "ns" "name") (param f64 i32) (result f64 i32)) -/// (func (export "name") (param f64 i32) (result f64 i32)) -/// (global (import "ns" "name") (type f64))) -pub fn parse_interface(mut input: &str) -> Result { - let mut interface = Interface::default(); - let interface_inner = preceded( - tag("interface"), - tuple(( - opt(preceded(space_comments, identifier)), - many0(parse_func_or_global), - )), - ); - let interface_parser = preceded(space_comments, s_exp(interface_inner)); - - if let Result::Ok((inp, (sig_id, out))) = interface_parser(input) { - interface.name = sig_id.map(|s_id| s_id.to_string()); - - for entry in out.into_iter() { - match entry { - Either::Left(import) => { - if let Some(dup) = interface.imports.insert(import.get_key(), import) { - return Err(format!("Duplicate import found {:?}", dup)); - } - } - Either::Right(export) => { - if let Some(dup) = interface.exports.insert(export.get_key(), export) { - return Err(format!("Duplicate export found {:?}", dup)); - } - } - } - } - input = inp; - } - // catch trailing comments and spaces - if let Ok((inp, _)) = space_comments(input) { - input = inp; - } - if !input.is_empty() { - Err(format!("Could not parse remaining input: {}", input)) - } else { - Ok(interface) - } -} - -fn parse_comment(input: &str) -> IResult<&str, ()> { - map( - preceded(multispace0, preceded(char(';'), many0(is_not("\n")))), - |_| (), - )(input) -} - -/// Consumes spaces and comments -/// comments must terminate with a new line character -fn space_comments<'a>(mut input: &'a str) -> IResult<&'a str, ()> { - let mut space_found = true; - let mut comment_found = true; - while space_found || comment_found { - let space: IResult<&'a str, _> = multispace1(input); - space_found = if let Result::Ok((inp, _)) = space { - input = inp; - true - } else { - false - }; - comment_found = if let Result::Ok((inp, _)) = parse_comment(input) { - input = inp; - true - } else { - false - }; - } - Ok((input, ())) -} - -/// A quoted identifier, must be valid UTF8 -fn identifier(input: &str) -> IResult<&str, &str> { - let name_inner = escaped(is_not("\"\\"), '\\', one_of("\"n\\")); - context("identifier", delimited(char('"'), name_inner, char('"')))(input) -} - -/// Parses a wasm primitive type -fn wasm_type(input: &str) -> IResult<&str, WasmType> { - let i32_tag = map(tag("i32"), |_| WasmType::I32); - let i64_tag = map(tag("i64"), |_| WasmType::I64); - let f32_tag = map(tag("f32"), |_| WasmType::F32); - let f64_tag = map(tag("f64"), |_| WasmType::F64); - - alt((i32_tag, i64_tag, f32_tag, f64_tag))(input) -} - -/// Parses an S-expression -fn s_exp<'a, O1, F>(inner: F) -> impl Fn(&'a str) -> IResult<&'a str, O1> -where - F: Fn(&'a str) -> IResult<&'a str, O1>, -{ - delimited( - char('('), - preceded(space_comments, inner), - preceded(space_comments, char(')')), - ) -} - -fn parse_func_or_global(input: &str) -> IResult<&str, Either> { - preceded(space_comments, alt((func, global)))(input) -} - -/// (func (import "ns" "name") (param f64 i32) (result f64 i32)) -/// (func (export "name") (param f64 i32) (result f64 i32)) -fn func(input: &str) -> IResult<&str, Either> { - let param_list_inner = preceded(tag("param"), many0(preceded(space_comments, wasm_type))); - let param_list = opt(s_exp(param_list_inner)); - let result_list_inner = preceded(tag("result"), many0(preceded(space_comments, wasm_type))); - let result_list = opt(s_exp(result_list_inner)); - let import_id_inner = preceded( - tag("import"), - tuple(( - preceded(space_comments, identifier), - preceded(space_comments, identifier), - )), - ); - let export_id_inner = preceded(tag("export"), preceded(space_comments, identifier)); - let func_id_inner = alt(( - map(import_id_inner, |(ns, name)| { - Either::Left((ns.to_string(), name.to_string())) - }), - map(export_id_inner, |name| Either::Right(name.to_string())), - )); - let func_id = s_exp(func_id_inner); - let func_import_inner = context( - "func import inner", - preceded( - tag("func"), - map( - tuple(( - preceded(space_comments, func_id), - preceded(space_comments, param_list), - preceded(space_comments, result_list), - )), - |(func_id, pl, rl)| match func_id { - Either::Left((ns, name)) => Either::Left(Import::Func { - namespace: ns, - name, - params: pl.unwrap_or_default(), - result: rl.unwrap_or_default(), - }), - Either::Right(name) => Either::Right(Export::Func { - name, - params: pl.unwrap_or_default(), - result: rl.unwrap_or_default(), - }), - }, - ), - ), - ); - s_exp(func_import_inner)(input) -} - -/// (global (import "ns" "name") (type f64)) -/// (global (export "name") (type f64)) -fn global(input: &str) -> IResult<&str, Either> { - let global_type_inner = preceded(tag("type"), preceded(space_comments, wasm_type)); - let type_s_exp = s_exp(global_type_inner); - let export_inner = preceded(tag("export"), preceded(space_comments, identifier)); - let import_inner = preceded( - tag("import"), - tuple(( - preceded(space_comments, identifier), - preceded(space_comments, identifier), - )), - ); - let global_id_inner = alt(( - map(import_inner, |(ns, name)| { - Either::Left(Import::Global { - namespace: ns.to_string(), - name: name.to_string(), - // placeholder type, overwritten in `global_inner` - var_type: WasmType::I32, - }) - }), - map(export_inner, |name| { - Either::Right(Export::Global { - name: name.to_string(), - // placeholder type, overwritten in `global_inner` - var_type: WasmType::I32, - }) - }), - )); - let global_id = s_exp(global_id_inner); - let global_inner = context( - "global inner", - preceded( - tag("global"), - map( - tuple(( - preceded(space_comments, global_id), - preceded(space_comments, type_s_exp), - )), - |(import_or_export, var_type)| match import_or_export { - Either::Left(Import::Global { - namespace, name, .. - }) => Either::Left(Import::Global { - namespace, - name, - var_type, - }), - Either::Right(Export::Global { name, .. }) => { - Either::Right(Export::Global { name, var_type }) - } - _ => unreachable!("Invalid value interonally in parse global function"), - }, - ), - ), - ); - s_exp(global_inner)(input) -} - -#[cfg(test)] -mod test { - use super::*; - use std::collections::HashMap; - - #[test] - fn parse_wasm_type() { - let i32_res = wasm_type("i32").unwrap(); - assert_eq!(i32_res, ("", WasmType::I32)); - let i64_res = wasm_type("i64").unwrap(); - assert_eq!(i64_res, ("", WasmType::I64)); - let f32_res = wasm_type("f32").unwrap(); - assert_eq!(f32_res, ("", WasmType::F32)); - let f64_res = wasm_type("f64").unwrap(); - assert_eq!(f64_res, ("", WasmType::F64)); - - assert!(wasm_type("i128").is_err()); - } - - #[test] - fn parse_identifier() { - let inner_str = "柴は可愛すぎるだと思います"; - let input = format!("\"{}\"", &inner_str); - let parse_res = identifier(&input).unwrap(); - assert_eq!(parse_res, ("", inner_str)) - } - - #[test] - fn parse_global_import() { - let parse_res = global(r#"(global (import "env" "length") (type i32))"#) - .ok() - .and_then(|(a, b)| Some((a, b.left()?))) - .unwrap(); - assert_eq!( - parse_res, - ( - "", - Import::Global { - namespace: "env".to_string(), - name: "length".to_string(), - var_type: WasmType::I32, - } - ) - ); - } - - #[test] - fn parse_global_export() { - let parse_res = global(r#"(global (export "length") (type i32))"#) - .ok() - .and_then(|(a, b)| Some((a, b.right()?))) - .unwrap(); - assert_eq!( - parse_res, - ( - "", - Export::Global { - name: "length".to_string(), - var_type: WasmType::I32, - } - ) - ); - } - - #[test] - fn parse_func_import() { - let parse_res = func(r#"(func (import "ns" "name") (param f64 i32) (result f64 i32))"#) - .ok() - .and_then(|(a, b)| Some((a, b.left()?))) - .unwrap(); - assert_eq!( - parse_res, - ( - "", - Import::Func { - namespace: "ns".to_string(), - name: "name".to_string(), - params: vec![WasmType::F64, WasmType::I32], - result: vec![WasmType::F64, WasmType::I32], - } - ) - ); - } - - #[test] - fn parse_func_export() { - let parse_res = func(r#"(func (export "name") (param f64 i32) (result f64 i32))"#) - .ok() - .and_then(|(a, b)| Some((a, b.right()?))) - .unwrap(); - assert_eq!( - parse_res, - ( - "", - Export::Func { - name: "name".to_string(), - params: vec![WasmType::F64, WasmType::I32], - result: vec![WasmType::F64, WasmType::I32], - } - ) - ); - - let parse_res = func(r#"(func (export "name"))"#) - .ok() - .and_then(|(a, b)| Some((a, b.right()?))) - .unwrap(); - assert_eq!( - parse_res, - ( - "", - Export::Func { - name: "name".to_string(), - params: vec![], - result: vec![], - } - ) - ) - } - - #[test] - fn parse_imports_test() { - let parse_imports = |in_str| { - many0(parse_func_or_global)(in_str) - .map(|(a, b)| { - ( - a, - b.into_iter().filter_map(|x| x.left()).collect::>(), - ) - }) - .unwrap() - }; - let parse_res = - parse_imports(r#"(func (import "ns" "name") (param f64 i32) (result f64 i32))"#); - assert_eq!( - parse_res, - ( - "", - vec![Import::Func { - namespace: "ns".to_string(), - name: "name".to_string(), - params: vec![WasmType::F64, WasmType::I32], - result: vec![WasmType::F64, WasmType::I32], - }] - ) - ); - - let parse_res = parse_imports( - r#"(func (import "ns" "name") - (param f64 i32) (result f64 i32)) - ( global ( import "env" "length" ) ( type - ;; i32 is the best type - i32 ) - ) - (func (import "ns" "name2") (param f32 - i64) - ;; The return value comes next - ( - result - f64 - i32 - ) - )"#, - ); - assert_eq!( - parse_res, - ( - "", - vec![ - Import::Func { - namespace: "ns".to_string(), - name: "name".to_string(), - params: vec![WasmType::F64, WasmType::I32], - result: vec![WasmType::F64, WasmType::I32], - }, - Import::Global { - namespace: "env".to_string(), - name: "length".to_string(), - var_type: WasmType::I32, - }, - Import::Func { - namespace: "ns".to_string(), - name: "name2".to_string(), - params: vec![WasmType::F32, WasmType::I64], - result: vec![WasmType::F64, WasmType::I32], - }, - ] - ) - ); - } - - #[test] - fn top_level_test() { - let parse_res = parse_interface( - r#" (interface - (func (import "ns" "name") (param f64 i32) (result f64 i32)) - (func (export "name2") (param) (result i32)) - (global (import "env" "length") (type f64)))"#, - ) - .unwrap(); - - let imports = vec![ - Import::Func { - namespace: "ns".to_string(), - name: "name".to_string(), - params: vec![WasmType::F64, WasmType::I32], - result: vec![WasmType::F64, WasmType::I32], - }, - Import::Global { - namespace: "env".to_string(), - name: "length".to_string(), - var_type: WasmType::F64, - }, - ]; - let exports = vec![Export::Func { - name: "name2".to_string(), - params: vec![], - result: vec![WasmType::I32], - }]; - let import_map = imports - .into_iter() - .map(|entry| (entry.get_key(), entry)) - .collect::>(); - let export_map = exports - .into_iter() - .map(|entry| (entry.get_key(), entry)) - .collect::>(); - assert_eq!( - parse_res, - Interface { - name: None, - imports: import_map, - exports: export_map, - } - ); - } - - #[test] - fn duplicates_not_allowed() { - let parse_res = parse_interface( - r#" (interface "sig_name" (func (import "ns" "name") (param f64 i32) (result f64 i32)) -; test comment - ;; hello - (func (import "ns" "name") (param) (result i32)) - (global (export "length") (type f64))) - -"#, - ); - - assert!(parse_res.is_err()); - } - - #[test] - fn test_comment_space_parsing() { - let parse_res = space_comments(" ").unwrap(); - assert_eq!(parse_res, ("", ())); - let parse_res = space_comments("").unwrap(); - assert_eq!(parse_res, ("", ())); - let parse_res = space_comments("; hello\n").unwrap(); - assert_eq!(parse_res, ("", ())); - let parse_res = space_comments("abc").unwrap(); - assert_eq!(parse_res, ("abc", ())); - let parse_res = space_comments("\n ; hello\n ").unwrap(); - assert_eq!(parse_res, ("", ())); - let parse_res = space_comments("\n ; hello\n ; abc\n\n ; hello\n").unwrap(); - assert_eq!(parse_res, ("", ())); - } - - #[test] - fn test_param_elision() { - let parse_res = parse_interface( - r#" (interface "interface_name" (func (import "ns" "name") (result f64 i32)) -(func (export "name"))) -"#, - ) - .unwrap(); - - let imports = vec![Import::Func { - namespace: "ns".to_string(), - name: "name".to_string(), - params: vec![], - result: vec![WasmType::F64, WasmType::I32], - }]; - let exports = vec![Export::Func { - name: "name".to_string(), - params: vec![], - result: vec![], - }]; - let import_map = imports - .into_iter() - .map(|entry| (entry.get_key(), entry)) - .collect::>(); - let export_map = exports - .into_iter() - .map(|entry| (entry.get_key(), entry)) - .collect::>(); - assert_eq!( - parse_res, - Interface { - name: Some("interface_name".to_string()), - imports: import_map, - exports: export_map, - } - ); - } - - #[test] - fn typo_gets_caught() { - let interface_src = r#" -(interface "interface_id" -(func (import "env" "do_panic") (params i32 i64)) -(global (import "length") (type i32)))"#; - let result = parse_interface(interface_src); - assert!(result.is_err()); - } - - #[test] - fn parse_trailing_spaces_on_interface() { - let parse_res = parse_interface( - r#" (interface "really_good_interface" (func (import "ns" "name") (param f64 i32) (result f64 i32)) -; test comment - ;; hello - (global (import "ns" "length") (type f64)) -) - -"#, - ); - - assert!(parse_res.is_ok()); - } -} diff --git a/lib/wasm-interface/src/validate.rs b/lib/wasm-interface/src/validate.rs deleted file mode 100644 index 71785fcdc4c..00000000000 --- a/lib/wasm-interface/src/validate.rs +++ /dev/null @@ -1,507 +0,0 @@ -//! Validate a wasm module given a interface. -//! -//! This checks that all imports are specified in the interface and that their types -//! are correct, as well as that all exports that the interface expects are exported -//! by the module and that their types are correct. - -use crate::{Export, Import, Interface, WasmType}; -use std::collections::HashMap; -use wasmparser::{ - CompositeInnerType, ExternalKind, FuncType, GlobalType, Payload, TypeRef, WasmFeatures, -}; - -pub fn validate_wasm_and_report_errors( - wasm: &[u8], - interface: &Interface, -) -> Result<(), WasmValidationError> { - let mut errors: Vec = vec![]; - let mut import_fns: HashMap<(String, String), u32> = HashMap::new(); - let mut export_fns: HashMap = HashMap::new(); - let mut export_globals: HashMap = HashMap::new(); - let mut type_defs: Vec = vec![]; - let mut global_types: Vec = vec![]; - let mut fn_sigs: Vec = vec![]; - - let mut wasm_features = WasmFeatures::default(); - wasm_features.set(WasmFeatures::THREADS, true); - wasm_features.set(WasmFeatures::REFERENCE_TYPES, true); - wasm_features.set(WasmFeatures::SIMD, true); - wasm_features.set(WasmFeatures::BULK_MEMORY, true); - wasm_features.set(WasmFeatures::MULTI_VALUE, true); - wasm_features.set(WasmFeatures::GC_TYPES, true); - - let mut val = wasmparser::Validator::new_with_features(wasm_features); - - val.validate_all(wasm) - .map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - let parser = wasmparser::Parser::new(0).parse_all(wasm); - - for res in parser { - let payload = res.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - match payload { - Payload::End(_) => break, - Payload::ImportSection(reader) => { - for item in reader.into_iter_with_offsets() { - let (_offset, import) = item.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - match import.ty { - TypeRef::Func(idx) => { - import_fns.insert(Import::format_key(import.module, import.name), idx); - fn_sigs.push(idx); - } - TypeRef::Global(GlobalType { content_type, .. }) => { - let global_type = wasmparser_type_into_wasm_type(content_type) - .map_err(|err| WasmValidationError::UnsupportedType { - error: format!( - "Invalid type found in import \"{}\" \"{}\": {}", - import.module, import.name, err - ), - })?; - if let Some(val) = interface - .imports - .get(&Import::format_key(import.module, import.name)) - { - if let Import::Global { var_type, .. } = val { - if *var_type != global_type { - errors.push(format!( - "Invalid type on Global \"{}\". Expected {} found {}", - import.name, var_type, global_type - )); - } - } else { - errors.push(format!( - "Invalid import type. Expected Global, found {:?}", - val - )); - } - } else { - errors.push(format!( - "Global import \"{}\" not found in the specified interface", - import.name - )); - } - } - _ => (), - } - } - } - Payload::ExportSection(reader) => { - for res in reader.into_iter() { - let export = res.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - match export.kind { - ExternalKind::Func => { - export_fns.insert(Export::format_key(export.name), export.index); - } - ExternalKind::Global => { - export_globals.insert(Export::format_key(export.name), export.index); - } - _ => (), - } - } - } - Payload::GlobalSection(reader) => { - for res in reader.into_iter() { - let global = res.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - global_types.push(global.ty); - } - } - Payload::TypeSection(reader) => { - for res in reader.into_iter() { - let group = res.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - for ty in group.into_types() { - if let CompositeInnerType::Func(ft) = ty.composite_type.inner { - type_defs.push(ft); - } - } - } - } - Payload::FunctionSection(reader) => { - for res in reader.into_iter() { - let func = res.map_err(|e| WasmValidationError::InvalidWasm { - error: format!("{}", e), - })?; - - fn_sigs.push(func); - } - } - _ => {} - } - } - - validate_imports(&import_fns, &type_defs, interface, &mut errors); - validate_export_fns(&export_fns, &type_defs, &fn_sigs, interface, &mut errors); - validate_export_globals(&export_globals, &global_types, interface, &mut errors); - - if errors.is_empty() { - Ok(()) - } else { - Err(WasmValidationError::InterfaceViolated { errors }) - } -} - -/// Validates the import functions, checking the name and type against the given -/// `Interface` -fn validate_imports( - import_fns: &HashMap<(String, String), u32>, - type_defs: &[FuncType], - interface: &Interface, - errors: &mut Vec, -) { - for (key, val) in import_fns.iter() { - if let Some(interface_def) = interface.imports.get(key) { - let type_sig = if let Some(v) = type_defs.get(*val as usize) { - v - } else { - errors.push(format!( - "Use of undeclared function reference \"{}\" in import function \"{}\" \"{}\"", - val, key.0, key.1 - )); - continue; - }; - if let Import::Func { params, result, .. } = interface_def { - for (i, param) in type_sig - .params() - .iter() - .cloned() - .map(wasmparser_type_into_wasm_type) - .enumerate() - { - match param { - Ok(t) => { - if params.get(i).is_none() { - errors.push(format!("Found {} args but the interface only expects {} for imported function \"{}\" \"{}\"", i, params.len(), &key.0, &key.1)); - continue; - } - if t != params[i] { - errors.push(format!( - "Type mismatch in params in imported func \"{}\" \"{}\": argument {}, expected {} found {}", - &key.0, &key.1, i + 1, params[i], t - )); - } - } - Err(e) => errors.push(format!( - "Invalid type in func \"{}\" \"{}\": {}", - &key.0, &key.1, e - )), - } - } - for (i, ret) in type_sig - .results() - .iter() - .cloned() - .map(wasmparser_type_into_wasm_type) - .enumerate() - { - match ret { - Ok(t) => { - if result.get(i).is_none() { - errors.push(format!("Found {} returns but the interface only expects {} for imported function \"{}\" \"{}\"", i, params.len(), &key.0, &key.1)); - continue; - } - - if t != result[i] { - errors.push(format!( - "Type mismatch in returns in func \"{}\" \"{}\", return {}, expected {} found {}", - &key.0, &key.1, i + 1, params[i], t - )); - } - } - Err(e) => errors.push(format!( - "Invalid type in func \"{}\" \"{}\": {}", - &key.0, &key.1, e - )), - } - } - } - } else { - // we didn't find the import at all in the interface - // TODO: improve error messages by including type information - errors.push(format!("Missing import \"{}\" \"{}\"", key.0, key.1)); - } - } -} - -/// Validates the export functions, checking the name and type against the given -/// `Interface` -fn validate_export_fns( - export_fns: &HashMap, - type_defs: &[FuncType], - fn_sigs: &[u32], - interface: &Interface, - errors: &mut Vec, -) { - 'export_loop: for (key, val) in export_fns.iter() { - if let Some(interface_def) = interface.exports.get(key) { - let type_sig = if let Some(type_idx) = fn_sigs.get(*val as usize) { - if let Some(v) = type_defs.get(*type_idx as usize) { - v - } else { - errors.push(format!( - "Export \"{}\" refers to type \"{}\" but only {} types were found", - &key, - type_idx, - fn_sigs.len() - )); - continue; - } - } else { - errors.push(format!( - "Use of undeclared function reference \"{}\" in export \"{}\"", - val, &key - )); - continue; - }; - if let Export::Func { params, result, .. } = interface_def { - for (i, param) in type_sig - .params() - .iter() - .cloned() - .map(wasmparser_type_into_wasm_type) - .enumerate() - { - match param { - Ok(t) => { - if params.get(i).is_none() { - errors.push(format!("Found {} args but the interface only expects {} for exported function \"{}\"", type_sig.params().len(), params.len(), &key)); - continue 'export_loop; - } - if t != params[i] { - errors.push(format!( - "Type mismatch in params in exported func \"{}\": in argument {}, expected {} found {}", - &key, i + 1, params[i], t - )); - } - } - Err(e) => errors - .push(format!("Invalid type in exported func \"{}\": {}", &key, e)), - } - } - for (i, ret) in type_sig - .results() - .iter() - .cloned() - .map(wasmparser_type_into_wasm_type) - .enumerate() - { - match ret { - Ok(t) => { - if result.get(i).is_none() { - errors.push(format!("Found {} returns but the interface only expects {} for exported function \"{}\"", i, params.len(), &key)); - continue 'export_loop; - } - - if t != result[i] { - errors.push(format!( - "Type mismatch in returns in exported func \"{}\": in return {}, expected {} found {}", - &key, i + 1, result[i], t - )); - } - } - Err(e) => errors - .push(format!("Invalid type in exported func \"{}\": {}", &key, e)), - } - } - } - } - } -} - -/// Validates the export globals, checking the name and type against the given -/// `Interface` -fn validate_export_globals( - export_globals: &HashMap, - global_types: &[GlobalType], - interface: &Interface, - errors: &mut Vec, -) { - for (key, val) in export_globals.iter() { - if let Some(Export::Global { var_type, .. }) = interface.exports.get(key) { - if global_types.get(*val as usize).is_none() { - errors.push(format!( - "Invalid wasm, expected {} global types, found {}", - val, - global_types.len() - )); - } - match wasmparser_type_into_wasm_type(global_types[*val as usize].content_type) { - Ok(t) => { - if *var_type != t { - errors.push(format!( - "Type mismatch in global export {}: expected {} found {}", - &key, var_type, t - )); - } - } - Err(e) => errors.push(format!("In global export {}: {}", &key, e)), - } - } - } -} - -/// Converts Wasmparser's type enum into wasm-interface's type enum -/// wasmparser's enum contains things which are invalid in many situations -/// -/// Additionally wasmerparser containers more advanced types like references that -/// wasm-interface does not yet support -fn wasmparser_type_into_wasm_type(ty: wasmparser::ValType) -> Result { - use wasmparser::ValType; - Ok(match ty { - ValType::I32 => WasmType::I32, - ValType::I64 => WasmType::I64, - ValType::F32 => WasmType::F32, - ValType::F64 => WasmType::F64, - e => { - return Err(format!("Invalid type found: {:?}", e)); - } - }) -} - -#[cfg(test)] -mod validation_tests { - use super::*; - use crate::parser; - - #[test] - fn global_imports() { - const WAT: &str = r#"(module -(type $t0 (func (param i32 i64))) -(global $length (import "env" "length") i32) -(import "env" "do_panic" (func $do_panic (type $t0))) -)"#; - let wasm = wat::parse_str(WAT).unwrap(); - - let interface_src = r#" -(interface -(func (import "env" "do_panic") (param i32 i64)) -(global (import "env" "length") (type i32)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!(result.is_ok()); - - // Now set the global import type to mismatch the wasm - let interface_src = r#" -(interface -(func (import "env" "do_panic") (param i32 i64)) -(global (import "env" "length") (type i64)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!( - result.is_err(), - "global import type mismatch causes an error" - ); - - // Now set the function import type to mismatch the wasm - let interface_src = r#" -(interface -(func (import "env" "do_panic") (param i64)) -(global (import "env" "length") (type i32)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!( - result.is_err(), - "function import type mismatch causes an error" - ); - - // Now try with a module that has an import that the interface doesn't have - let interface_src = r#" -(interface -(func (import "env" "do_panic") (param i64)) -(global (import "env" "length_plus_plus") (type i32)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!( - result.is_err(), - "all imports must be covered by the interface" - ); - } - - #[test] - fn global_exports() { - const WAT: &str = r#"(module -(func (export "as-local.set-first") (param i32) (result i32) - (nop) (i32.const 2) (local.set 0) (local.get 0)) -(global (export "num_tries") i64 (i64.const 0)) -)"#; - let wasm = wat::parse_str(WAT).unwrap(); - - let interface_src = r#" -(interface -(func (export "as-local.set-first") (param i32) (result i32)) -(global (export "num_tries") (type i64)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!(result.is_ok()); - - // Now set the global export type to mismatch the wasm - let interface_src = r#" -(interface -(func (export "as-local.set-first") (param i32) (result i32)) -(global (export "num_tries") (type f32)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!( - result.is_err(), - "global export type mismatch causes an error" - ); - - // Now set the function export type to mismatch the wasm - let interface_src = r#" -(interface -(func (export "as-local.set-first") (param i64) (result i64)) -(global (export "num_tries") (type i64)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!( - result.is_err(), - "function export type mismatch causes an error" - ); - - // Now try a interface that requires an export that the module doesn't have - let interface_src = r#" -(interface -(func (export "as-local.set-first") (param i64) (result i64)) -(global (export "numb_trees") (type i64)))"#; - let interface = parser::parse_interface(interface_src).unwrap(); - - let result = validate_wasm_and_report_errors(&wasm[..], &interface); - - assert!(result.is_err(), "missing a required export is an error"); - } -} - -#[derive(Debug)] -pub enum WasmValidationError { - InvalidWasm { error: String }, - InterfaceViolated { errors: Vec }, - UnsupportedType { error: String }, -} diff --git a/tests/integration/cli/Cargo.toml b/tests/integration/cli/Cargo.toml index 18c238bf2c2..2fbc579caf4 100644 --- a/tests/integration/cli/Cargo.toml +++ b/tests/integration/cli/Cargo.toml @@ -33,7 +33,6 @@ tar = "0.4.38" flate2 = "1.0.24" dirs = "4.0.0" derivative = { version = "^2" } -wasmer-registry = { path = "../../../lib/registry", default-features = false } [features] default = ["webc_runner"] diff --git a/tests/integration/cli/tests/config.rs b/tests/integration/cli/tests/config.rs index 491ae4b2589..d4e506b21bf 100644 --- a/tests/integration/cli/tests/config.rs +++ b/tests/integration/cli/tests/config.rs @@ -1,16 +1,41 @@ -use std::path::Path; +use std::{fs::OpenOptions, io::Write, path::Path}; use assert_cmd::Command; use predicates::str::contains; use tempfile::TempDir; use wasmer_integration_tests_cli::get_wasmer_path; -use wasmer_registry::WasmerConfig; fn setup_wasmer_dir() -> TempDir { let temp = TempDir::new().unwrap(); - let config_path = WasmerConfig::get_file_location(temp.path()); - WasmerConfig::default().save(&config_path).unwrap(); + // The config path and the config contents themselves are manually crafted so that we don't + // depend on the cli crate. + // + // Eventually, this part of the config shall live on a freestanding crate - perhaps added to + // `wasmer-config`. + let config_path = temp.path().join("wasmer.toml"); + + let contents = r#" +telemetry_enabled = true +update_notifications_enabled = true + +[registry] +active_registry = "https://registry.wasmer.io/graphql" + +[[registry.tokens]] +registry = "https://registry.wasmer.io/graphql" + +[proxy] + "#; + + let mut file = OpenOptions::new() + .create(true) + .truncate(true) + .write(true) + .open(&config_path) + .unwrap(); + + file.write_all(contents.as_bytes()).unwrap(); temp }