From 09d1e72ac597c7b606e97044ff36002f2df836fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tanguy=20G=C3=A9r=C3=B4me?= Date: Mon, 21 Oct 2024 19:40:51 +0300 Subject: [PATCH] Initial WIP commit --- .gitignore | 13 + Cargo.lock | 2327 +++++++++++++++++++++++++++++++++ Cargo.toml | 106 ++ LICENSE | 24 + Procfile | 1 + README.md | 90 ++ end2end/package-lock.json | 167 +++ end2end/package.json | 15 + end2end/playwright.config.ts | 105 ++ end2end/tests/example.spec.ts | 9 + end2end/tsconfig.json | 109 ++ nixpacks.toml | 13 + public/favicon.ico | Bin 0 -> 25487 bytes run.sh | 2 + rust-toolchain.toml | 4 + src/app.rs | 81 ++ src/error_template.rs | 72 + src/fileserv.rs | 60 + src/lib.rs | 12 + src/main.rs | 38 + style/main.scss | 154 +++ 21 files changed, 3402 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 LICENSE create mode 100644 Procfile create mode 100644 README.md create mode 100644 end2end/package-lock.json create mode 100644 end2end/package.json create mode 100644 end2end/playwright.config.ts create mode 100644 end2end/tests/example.spec.ts create mode 100644 end2end/tsconfig.json create mode 100644 nixpacks.toml create mode 100644 public/favicon.ico create mode 100755 run.sh create mode 100644 rust-toolchain.toml create mode 100644 src/app.rs create mode 100644 src/error_template.rs create mode 100644 src/fileserv.rs create mode 100644 src/lib.rs create mode 100644 src/main.rs create mode 100644 style/main.scss diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..8cdaa33 --- /dev/null +++ b/.gitignore @@ -0,0 +1,13 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ +pkg + +# These are backup files generated by rustfmt +**/*.rs.bk + +# node e2e test tools and outputs +node_modules/ +test-results/ +end2end/playwright-report/ +playwright/.cache/ diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..4584008 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,2327 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "ahash" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] +name = "aho-corasick" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" +dependencies = [ + "memchr", +] + +[[package]] +name = "allocator-api2" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" + +[[package]] +name = "anyhow" +version = "1.0.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bf3594c4c988a53154954629820791dde498571819ae4ca50ca811e060cc95" + +[[package]] +name = "async-recursion" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b43422f69d8ff38f95f1b2bb76517c91589a924d1559a0e935d7c8ce0274c11" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "async-trait" +version = "0.1.83" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "721cae7de5c34fbb2acd27e21e6d2cf7b886dce0c27388d46c4e6c47ea4318dd" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "attribute-derive" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f1ee502851995027b06f99f5ffbeffa1406b38d0b318a1ebfa469332c6cbafd" +dependencies = [ + "attribute-derive-macro", + "derive-where", + "manyhow", + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "attribute-derive-macro" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3601467f634cfe36c4780ca9c75dea9a5b34529c1f2810676a337e7e0997f954" +dependencies = [ + "collection_literals", + "interpolator", + "manyhow", + "proc-macro-utils 0.8.0", + "proc-macro2", + "quote", + "quote-use", + "syn 2.0.82", +] + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "axum" +version = "0.7.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "504e3947307ac8326a5437504c517c4b56716c9d98fac0028c2acc7ca47d70ae" +dependencies = [ + "async-trait", + "axum-core", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper 1.0.1", + "tokio", + "tower 0.5.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 1.0.1", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "bitflags" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" + +[[package]] +name = "bumpalo" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" + +[[package]] +name = "bytes" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" + +[[package]] +name = "cached" +version = "0.45.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90eb5776f28a149524d1d8623035760b4454ec881e8cf3838fa8d7e1b11254b3" +dependencies = [ + "cached_proc_macro", + "cached_proc_macro_types", + "hashbrown 0.13.2", + "instant", + "once_cell", + "thiserror", +] + +[[package]] +name = "cached_proc_macro" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c878c71c2821aa2058722038a59a67583a4240524687c6028571c9b395ded61f" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "cached_proc_macro_types" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ade8366b8bd5ba243f0a58f036cc0ca8a2f069cff1a2351ef1cac6b083e16fc0" + +[[package]] +name = "camino" +version = "1.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "ciborium" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" +dependencies = [ + "ciborium-io", + "ciborium-ll", + "serde", +] + +[[package]] +name = "ciborium-io" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" + +[[package]] +name = "ciborium-ll" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" +dependencies = [ + "ciborium-io", + "half", +] + +[[package]] +name = "collection_literals" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "186dce98367766de751c42c4f03970fc60fc012296e706ccbb9d5df9b6c1e271" + +[[package]] +name = "config" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7328b20597b53c2454f0b1919720c25c7339051c02b72b7e05409e00b14132be" +dependencies = [ + "convert_case", + "lazy_static", + "nom", + "pathdiff", + "serde", + "toml", +] + +[[package]] +name = "console_error_panic_hook" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" +dependencies = [ + "cfg-if", + "wasm-bindgen", +] + +[[package]] +name = "const_format" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50c655d81ff1114fb0dcdea9225ea9f0cc712a6f8d189378e82bdf62a473a64b" +dependencies = [ + "const_format_proc_macros", +] + +[[package]] +name = "const_format_proc_macros" +version = "0.2.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eff1a44b93f47b1bac19a27932f5c591e43d1ba357ee4f61526c8a25603f0eb1" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "convert_case" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec182b0ca2f35d8fc196cf3404988fd8b8c739a4d270ff118a398feb0cbec1ca" +dependencies = [ + "unicode-segmentation", +] + +[[package]] +name = "crunchy" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" + +[[package]] +name = "darling" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b750cb3417fd1b327431a470f388520309479ab0bf5e323505daf0290cd3850" +dependencies = [ + "darling_core", + "darling_macro", +] + +[[package]] +name = "darling_core" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "109c1ca6e6b7f82cc233a97004ea8ed7ca123a9af07a8230878fcfda9b158bf0" +dependencies = [ + "fnv", + "ident_case", + "proc-macro2", + "quote", + "strsim", + "syn 1.0.109", +] + +[[package]] +name = "darling_macro" +version = "0.14.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4aab4dbc9f7611d8b55048a3a16d2d010c2c8334e46304b40ac1cc14bf3b48e" +dependencies = [ + "darling_core", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "dashmap" +version = "5.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" +dependencies = [ + "cfg-if", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + +[[package]] +name = "derive-where" +version = "1.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62d671cc41a825ebabc75757b62d3d168c577f9149b2d49ece1dad1f72119d25" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "drain_filter_polyfill" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" + +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "encoding_rs" +version = "0.8.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b45de904aa0b010bce2ab45264d0631681847fa7b6f2eaa7dab7619943bc4f59" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + +[[package]] +name = "futures" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", + "futures-sink", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-executor" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" +dependencies = [ + "futures-core", + "futures-task", + "futures-util", +] + +[[package]] +name = "futures-io" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" + +[[package]] +name = "futures-macro" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "futures-sink" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-macro", + "futures-sink", + "futures-task", + "memchr", + "pin-project-lite", + "pin-utils", + "slab", +] + +[[package]] +name = "getrandom" +version = "0.2.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi", + "wasm-bindgen", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "gloo-net" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" +dependencies = [ + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", + "js-sys", + "pin-project", + "serde", + "serde_json", + "thiserror", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "gloo-utils" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" +dependencies = [ + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "half" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" +dependencies = [ + "cfg-if", + "crunchy", +] + +[[package]] +name = "hashbrown" +version = "0.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a3c133739dddd0d2990f9a4bdf8eb4b21ef50e4851ca85ab661199821d510e" + +[[package]] +name = "hashbrown" +version = "0.14.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" +dependencies = [ + "ahash", + "allocator-api2", +] + +[[package]] +name = "hashbrown" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" + +[[package]] +name = "hermit-abi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" + +[[package]] +name = "html-escape" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d1ad449764d627e22bfd7cd5e8868264fc9236e07c752972b4080cd351cb476" +dependencies = [ + "utf8-width", +] + +[[package]] +name = "http" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21b9ddb458710bc376481b842f5da65cdf31522de232c1ca8146abce2a358258" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "http-range-header" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08a397c49fec283e3d6211adbe480be95aae5f304cfb923e9970e08956d5168a" + +[[package]] +name = "httparse" +version = "1.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbff0a806a4728c99295b254c8838933b5b082d75e3cb70c8dab21fdfbcfa9a" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41296eb09f183ac68eec06e03cdbea2e759633d4067b2f6552fc2e009bcad08b" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", + "tower-service", +] + +[[package]] +name = "ident_case" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" + +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + +[[package]] +name = "indexmap" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" +dependencies = [ + "equivalent", + "hashbrown 0.15.0", +] + +[[package]] +name = "instant" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0242819d153cba4b4b05a5a8f2a7e9bbf97b6055b2a002b395c96b5ff3c0222" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "interpolator" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8" + +[[package]] +name = "inventory" +version = "0.3.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f958d3d68f4167080a18141e10381e7634563984a537f2a49a30fd8e53ac5767" + +[[package]] +name = "itertools" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b" + +[[package]] +name = "js-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1868808506b929d7b0cfa8f75951347aa71bb21144b7791bae35d9bccfcfe37a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "leptos" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0cbb3237c274dadf00dcc27db96c52601b40375117178fb24a991cda073624f0" +dependencies = [ + "cfg-if", + "leptos_config", + "leptos_dom", + "leptos_macro", + "leptos_reactive", + "leptos_server", + "server_fn", + "tracing", + "typed-builder", + "typed-builder-macro", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "leptos_axum" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910681b920c48a43508b2bd0261bdb67c4ef9456a0b3613f956a0d30e832e9de" +dependencies = [ + "axum", + "cfg-if", + "futures", + "http-body-util", + "leptos", + "leptos_integration_utils", + "leptos_macro", + "leptos_meta", + "leptos_router", + "once_cell", + "parking_lot", + "serde_json", + "server_fn", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "leptos_config" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ed778611380ddea47568ac6ad6ec5158d39b5bd59e6c4dcd24efc15dc3dc0d" +dependencies = [ + "config", + "regex", + "serde", + "thiserror", + "typed-builder", +] + +[[package]] +name = "leptos_dom" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8401c46c86c1f4c16dcb7881ed319fcdca9cda9b9e78a6088955cb423afcf119" +dependencies = [ + "async-recursion", + "cfg-if", + "drain_filter_polyfill", + "futures", + "getrandom", + "html-escape", + "indexmap", + "itertools", + "js-sys", + "leptos_reactive", + "once_cell", + "pad-adapter", + "paste", + "rustc-hash", + "serde", + "serde_json", + "server_fn", + "smallvec", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "leptos_hot_reload" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6cb53d4794240b684a2f4be224b84bee9e62d2abc498cf2bcd643cd565e01d96" +dependencies = [ + "anyhow", + "camino", + "indexmap", + "parking_lot", + "proc-macro2", + "quote", + "rstml", + "serde", + "syn 2.0.82", + "walkdir", +] + +[[package]] +name = "leptos_integration_utils" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a96976631c2225ec116a7bf9c0ed5bf6999a19fed33f5e3cbcf37af44c384dc" +dependencies = [ + "futures", + "leptos", + "leptos_config", + "leptos_hot_reload", + "leptos_meta", + "tracing", +] + +[[package]] +name = "leptos_macro" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4b13bc3db70715cd8218c4535a5af3ae3c0e5fea6f018531fc339377b36bc0e0" +dependencies = [ + "attribute-derive", + "cfg-if", + "convert_case", + "html-escape", + "itertools", + "leptos_hot_reload", + "prettyplease", + "proc-macro-error2", + "proc-macro2", + "quote", + "rstml", + "server_fn_macro", + "syn 2.0.82", + "tracing", + "uuid", +] + +[[package]] +name = "leptos_meta" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25acc2f63cf91932013e400a95bf6e35e5d3dbb44a7b7e25a8e3057d12005b3b" +dependencies = [ + "cfg-if", + "indexmap", + "leptos", + "tracing", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "leptos_reactive" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4161acbf80f59219d8d14182371f57302bc7ff81ee41aba8ba1ff7295727f23" +dependencies = [ + "base64", + "cfg-if", + "futures", + "indexmap", + "js-sys", + "oco_ref", + "paste", + "pin-project", + "rustc-hash", + "self_cell", + "serde", + "serde-wasm-bindgen", + "serde_json", + "slotmap", + "thiserror", + "tokio", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "leptos_router" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d71dea7d42c0d29c40842750232d3425ed1cf10e313a1f898076d20871dad32" +dependencies = [ + "cached", + "cfg-if", + "gloo-net", + "itertools", + "js-sys", + "lazy_static", + "leptos", + "leptos_integration_utils", + "leptos_meta", + "linear-map", + "lru", + "once_cell", + "percent-encoding", + "regex", + "send_wrapper", + "serde", + "serde_json", + "serde_qs 0.13.0", + "thiserror", + "tracing", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "leptos_server" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4a97eb90a13f71500b831c7119ddd3bdd0d7ae0a6b0487cade4fddeed3b8c03f" +dependencies = [ + "inventory", + "lazy_static", + "leptos_macro", + "leptos_reactive", + "serde", + "server_fn", + "thiserror", + "tracing", +] + +[[package]] +name = "libc" +version = "0.2.161" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" + +[[package]] +name = "linear-map" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfae20f6b19ad527b550c223fddc3077a547fc70cda94b9b566575423fd303ee" +dependencies = [ + "serde", + "serde_test", +] + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "log" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" + +[[package]] +name = "lru" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4a83fb7698b3643a0e34f9ae6f2e8f0178c0fd42f8b59d493aa271ff3a5bf21" +dependencies = [ + "hashbrown 0.14.5", +] + +[[package]] +name = "manyhow" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f91ea592d76c0b6471965708ccff7e6a5d277f676b90ab31f4d3f3fc77fade64" +dependencies = [ + "manyhow-macros", + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "manyhow-macros" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c64621e2c08f2576e4194ea8be11daf24ac01249a4f53cd8befcbb7077120ead" +dependencies = [ + "proc-macro-utils 0.8.0", + "proc-macro2", + "quote", +] + +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "mime_guess" +version = "2.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" +dependencies = [ + "mime", + "unicase", +] + +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + +[[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", +] + +[[package]] +name = "object" +version = "0.36.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" +dependencies = [ + "memchr", +] + +[[package]] +name = "oco_ref" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c51ebcefb2f0b9a5e0bea115532c8ae4215d1b01eff176d0f4ba4192895c2708" +dependencies = [ + "serde", + "thiserror", +] + +[[package]] +name = "once_cell" +version = "1.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" + +[[package]] +name = "pad-adapter" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56d80efc4b6721e8be2a10a5df21a30fa0b470f1539e53d8b4e6e75faf938b63" + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pathdiff" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d61c5ce1153ab5b689d0c074c4e7fc613e942dfb7dd9eea5ab202d2ad91fe361" + +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + +[[package]] +name = "pin-project" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf123a161dde1e524adf36f90bc5d8d3462824a9c43553ad07a8183161189ec" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4502d8515ca9f32f1fb543d987f63d95a14934883db45bdb48060b6b69257f8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bda66fc9667c18cb2758a2ac84d1167245054bcf85d5d1aaa6923f45801bdd02" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "prettyplease" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910d41a655dac3b764f1ade94821093d3610248694320cd072303a8eedcf221d" +dependencies = [ + "proc-macro2", + "syn 2.0.82", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "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", +] + +[[package]] +name = "proc-macro-utils" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f59e109e2f795a5070e69578c4dc101068139f74616778025ae1011d4cd41a8" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + +[[package]] +name = "proc-macro-utils" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaf08a13de400bc215877b5bdc088f241b12eb42f0a548d3390dc1c56bb7071" +dependencies = [ + "proc-macro2", + "quote", + "smallvec", +] + +[[package]] +name = "proc-macro2" +version = "1.0.88" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c3a7fc5db1e57d5a779a352c8cdb57b29aa4c40cc69c3a68a7fedc815fbf2f9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", + "version_check", + "yansi", +] + +[[package]] +name = "quote" +version = "1.0.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "quote-use" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9619db1197b497a36178cfc736dc96b271fe918875fbf1344c436a7e93d0321e" +dependencies = [ + "quote", + "quote-use-macros", +] + +[[package]] +name = "quote-use-macros" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82ebfb7faafadc06a7ab141a6f67bcfb24cb8beb158c6fe933f2f035afa99f35" +dependencies = [ + "proc-macro-utils 0.10.0", + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "redox_syscall" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" +dependencies = [ + "bitflags", +] + +[[package]] +name = "regex" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38200e5ee88914975b69f657f0801b6f6dccafd44fd9326302a4aaeecfacb1d8" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" + +[[package]] +name = "rstml" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe542870b8f59dd45ad11d382e5339c9a1047cde059be136a7016095bbdefa77" +dependencies = [ + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "syn 2.0.82", + "syn_derive", + "thiserror", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + +[[package]] +name = "rustversion" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e819f2bc632f285be6d7cd36e25940d45b2391dd6d9b939e79de557f7014248" + +[[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" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "self_cell" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d369a96f978623eb3dc28807c4852d6cc617fed53da5d3c400feff1ef34a714a" + +[[package]] +name = "send_wrapper" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +dependencies = [ + "futures-core", +] + +[[package]] +name = "serde" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + +[[package]] +name = "serde_derive" +version = "1.0.210" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "serde_json" +version = "1.0.132" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" +dependencies = [ + "itoa", + "memchr", + "ryu", + "serde", +] + +[[package]] +name = "serde_path_to_error" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af99884400da37c88f5e9146b7f1fd0fbcae8f6eec4e9da38b67d05486f814a6" +dependencies = [ + "itoa", + "serde", +] + +[[package]] +name = "serde_qs" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0431a35568651e363364210c91983c1da5eb29404d9f0928b67d4ebcfa7d330c" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + +[[package]] +name = "serde_qs" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd34f36fe4c5ba9654417139a9b3a20d2e1de6012ee678ad14d240c22c78d8d6" +dependencies = [ + "percent-encoding", + "serde", + "thiserror", +] + +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_test" +version = "1.0.177" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f901ee573cab6b3060453d2d5f0bae4e6d628c23c0a962ff9b5f1d7c8d4f1ed" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_urlencoded" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +dependencies = [ + "form_urlencoded", + "itoa", + "ryu", + "serde", +] + +[[package]] +name = "server_fn" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fae7a3038a32e5a34ba32c6c45eb4852f8affaf8b794ebfcd4b1099e2d62ebe" +dependencies = [ + "axum", + "bytes", + "ciborium", + "const_format", + "dashmap", + "futures", + "gloo-net", + "http", + "http-body-util", + "hyper", + "inventory", + "js-sys", + "once_cell", + "send_wrapper", + "serde", + "serde_json", + "serde_qs 0.12.0", + "server_fn_macro_default", + "thiserror", + "tower 0.4.13", + "tower-layer", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams", + "web-sys", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "faaaf648c6967aef78177c0610478abb5a3455811f401f3c62d10ae9bd3901a1" +dependencies = [ + "const_format", + "convert_case", + "proc-macro2", + "quote", + "syn 2.0.82", + "xxhash-rust", +] + +[[package]] +name = "server_fn_macro_default" +version = "0.6.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2aa8119b558a17992e0ac1fd07f080099564f24532858811ce04f742542440" +dependencies = [ + "server_fn_macro", + "syn 2.0.82", +] + +[[package]] +name = "slab" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" +dependencies = [ + "autocfg", +] + +[[package]] +name = "slotmap" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dbff4acf519f630b3a3ddcfaea6c06b42174d9a44bc70c620e9ed1649d58b82a" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "spin" +version = "0.9.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" + +[[package]] +name = "strsim" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.82" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn_derive" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1329189c02ff984e9736652b1631330da25eaa6bc639089ed4915d25446cbe7b" +dependencies = [ + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + +[[package]] +name = "tanguy-gerome-fi" +version = "0.1.0" +dependencies = [ + "axum", + "console_error_panic_hook", + "http", + "leptos", + "leptos_axum", + "leptos_meta", + "leptos_router", + "thiserror", + "tokio", + "tower 0.4.13", + "tower-http", + "tracing", + "wasm-bindgen", +] + +[[package]] +name = "thiserror" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d50af8abc119fb8bb6dbabcfa89656f46f84aa0ac7688088608076ad2b459a84" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08904e7672f5eb876eaaf87e0ce17857500934f4981c4a0ab2b4aa98baac7fc3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "tokio" +version = "1.40.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2b070231665d27ad9ec9b8df639893f46727666c6767db40317fbe920a5d998" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "tokio-macros" +version = "2.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "tokio-util" +version = "0.7.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "futures-util", + "hashbrown 0.14.5", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "toml" +version = "0.8.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.22.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "pin-project", + "pin-project-lite", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2873938d487c3cfb9aed7546dc9f2711d867c9f90c46b889989a2cb84eba6b4f" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper 0.1.2", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e9cd434a998747dd2c4276bc96ee2e0c7a2eadf3cae88e52be55a05fa9053f5" +dependencies = [ + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "http-range-header", + "httpdate", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + +[[package]] +name = "tower-service" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" + +[[package]] +name = "tracing" +version = "0.1.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +dependencies = [ + "log", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "tracing-core" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +dependencies = [ + "once_cell", +] + +[[package]] +name = "typed-builder" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" +dependencies = [ + "typed-builder-macro", +] + +[[package]] +name = "typed-builder-macro" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] + +[[package]] +name = "unicase" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + +[[package]] +name = "unicode-ident" +version = "1.0.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" + +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "unicode-segmentation" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" + +[[package]] +name = "unicode-xid" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ebc1c04c71510c7f702b52b7c350734c9ff1295c464a03335b00bb84fc54f853" + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + +[[package]] +name = "utf8-width" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" + +[[package]] +name = "uuid" +version = "1.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" +dependencies = [ + "getrandom", +] + +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a82edfc16a6c469f5f44dc7b571814045d60404b55a0ee849f9bcfa2e63dd9b5" +dependencies = [ + "cfg-if", + "once_cell", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9de396da306523044d3302746f1208fa71d7532227f15e347e2d93e4145dd77b" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.82", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-futures" +version = "0.4.43" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61e9300f63a621e96ed275155c108eb6f843b6a26d053f122ab69724559dc8ed" +dependencies = [ + "cfg-if", + "js-sys", + "wasm-bindgen", + "web-sys", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "585c4c91a46b072c92e908d99cb1dcdf95c5218eeb6f3bf1efa991ee7a68cccf" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc340c74d9005395cf9dd098506f7f44e38f2b4a21c6aaacf9a105ea5e1e836" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62a0a307cb4a311d3a07867860911ca130c3494e8c2719593806c08bc5d0484" + +[[package]] +name = "wasm-streams" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e072d4e72f700fb3443d8fe94a39315df013eef1104903cdb0a2abd322bbecd" +dependencies = [ + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", +] + +[[package]] +name = "web-sys" +version = "0.3.70" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26fdeaafd9bd129f65e7c031593c24d62186301e0c72c8978fa1678be7d532c0" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" +dependencies = [ + "memchr", +] + +[[package]] +name = "xxhash-rust" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a5cbf750400958819fb6178eaa83bee5cd9c29a26a40cc241df8c70fdd46984" + +[[package]] +name = "yansi" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" + +[[package]] +name = "zerocopy" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.82", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..a7bdbf4 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,106 @@ +[package] +name = "tanguy-gerome-fi" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +axum = { version = "0.7", optional = true } +console_error_panic_hook = "0.1" +leptos = { version = "0.6", features = ["nightly"] } +leptos_axum = { version = "0.6", optional = true } +leptos_meta = { version = "0.6", features = ["nightly"] } +leptos_router = { version = "0.6", features = ["nightly"] } +tokio = { version = "1", features = ["rt-multi-thread"], optional = true } +tower = { version = "0.4", features = ["util"], optional = true } +tower-http = { version = "0.5", features = ["fs"], optional = true } +wasm-bindgen = "=0.2.93" +thiserror = "1" +tracing = { version = "0.1", optional = true } +http = "1" + +[features] +hydrate = ["leptos/hydrate", "leptos_meta/hydrate", "leptos_router/hydrate"] +ssr = [ + "dep:axum", + "dep:tokio", + "dep:tower", + "dep:tower-http", + "dep:leptos_axum", + "leptos/ssr", + "leptos_meta/ssr", + "leptos_router/ssr", + "dep:tracing", +] + +# Defines a size-optimized profile for the WASM bundle in release mode +[profile.wasm-release] +inherits = "release" +opt-level = 'z' +lto = true +codegen-units = 1 +panic = "abort" + +[package.metadata.leptos] +# The name used by wasm-bindgen/cargo-leptos for the JS/WASM bundle. Defaults to the crate name +output-name = "tanguy-gerome-fi" + +# The site root folder is where cargo-leptos generate all output. WARNING: all content of this folder will be erased on a rebuild. Use it in your server setup. +site-root = "target/site" + +# The site-root relative folder where all compiled output (JS, WASM and CSS) is written +# Defaults to pkg +site-pkg-dir = "pkg" + +# [Optional] The source CSS file. If it ends with .sass or .scss then it will be compiled by dart-sass into CSS. The CSS is optimized by Lightning CSS before being written to //app.css +style-file = "style/main.scss" +# Assets source dir. All files found here will be copied and synchronized to site-root. +# The assets-dir cannot have a sub directory with the same name/path as site-pkg-dir. +# +# Optional. Env: LEPTOS_ASSETS_DIR. +assets-dir = "public" + +# The IP and port (ex: 127.0.0.1:3000) where the server serves the content. Use it in your server setup. +site-addr = "127.0.0.1:3000" + +# The port to use for automatic reload monitoring +reload-port = 3001 + +# [Optional] Command to use when running end2end tests. It will run in the end2end dir. +# [Windows] for non-WSL use "npx.cmd playwright test" +# This binary name can be checked in Powershell with Get-Command npx +end2end-cmd = "npx playwright test" +end2end-dir = "end2end" + +# The browserlist query used for optimizing the CSS. +browserquery = "defaults" + +# The environment Leptos will run in, usually either "DEV" or "PROD" +env = "DEV" + +# The features to use when compiling the bin target +# +# Optional. Can be over-ridden with the command line parameter --bin-features +bin-features = ["ssr"] + +# If the --no-default-features flag should be used when compiling the bin target +# +# Optional. Defaults to false. +bin-default-features = false + +# The features to use when compiling the lib target +# +# Optional. Can be over-ridden with the command line parameter --lib-features +lib-features = ["hydrate"] + +# If the --no-default-features flag should be used when compiling the lib target +# +# Optional. Defaults to false. +lib-default-features = false + +# The profile to use for the lib target when compiling for release +# +# Optional. Defaults to "release". +lib-profile-release = "wasm-release" diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/Procfile b/Procfile new file mode 100644 index 0000000..f1a2542 --- /dev/null +++ b/Procfile @@ -0,0 +1 @@ +web: ./run.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..fd45658 --- /dev/null +++ b/README.md @@ -0,0 +1,90 @@ + + + Leptos Logo + + +# Leptos Axum Starter Template + +This is a template for use with the [Leptos](https://github.com/leptos-rs/leptos) web framework and the [cargo-leptos](https://github.com/akesson/cargo-leptos) tool using [Axum](https://github.com/tokio-rs/axum). + +## Creating your template repo + +If you don't have `cargo-leptos` installed you can install it with + +```bash +cargo install cargo-leptos --locked +``` + +Then run +```bash +cargo leptos new --git leptos-rs/start-axum +``` + +to generate a new project template. + +```bash +cd tanguy-gerome-fi +``` + +to go to your newly created project. +Feel free to explore the project structure, but the best place to start with your application code is in `src/app.rs`. +Addtionally, Cargo.toml may need updating as new versions of the dependencies are released, especially if things are not working after a `cargo update`. + +## Running your project + +```bash +cargo leptos watch +``` + +## Installing Additional Tools + +By default, `cargo-leptos` uses `nightly` Rust, `cargo-generate`, and `sass`. If you run into any trouble, you may need to install one or more of these tools. + +1. `rustup toolchain install nightly --allow-downgrade` - make sure you have Rust nightly +2. `rustup target add wasm32-unknown-unknown` - add the ability to compile Rust to WebAssembly +3. `cargo install cargo-generate` - install `cargo-generate` binary (should be installed automatically in future) +4. `npm install -g sass` - install `dart-sass` (should be optional in future + +## Compiling for Release +```bash +cargo leptos build --release +``` + +Will generate your server binary in target/server/release and your site package in target/site + +## Testing Your Project +```bash +cargo leptos end-to-end +``` + +```bash +cargo leptos end-to-end --release +``` + +Cargo-leptos uses Playwright as the end-to-end test tool. +Tests are located in end2end/tests directory. + +## Executing a Server on a Remote Machine Without the Toolchain +After running a `cargo leptos build --release` the minimum files needed are: + +1. The server binary located in `target/server/release` +2. The `site` directory and all files within located in `target/site` + +Copy these files to your remote server. The directory structure should be: +```text +tanguy-gerome-fi +site/ +``` +Set the following environment variables (updating for your project as needed): +```text +LEPTOS_OUTPUT_NAME="tanguy-gerome-fi" +LEPTOS_SITE_ROOT="site" +LEPTOS_SITE_PKG_DIR="pkg" +LEPTOS_SITE_ADDR="127.0.0.1:3000" +LEPTOS_RELOAD_PORT="3001" +``` +Finally, run the server binary. + +## Licensing + +This template itself is released under the Unlicense. You should replace the LICENSE for your own application with an appropriate license if you plan to release it publicly. diff --git a/end2end/package-lock.json b/end2end/package-lock.json new file mode 100644 index 0000000..260e8eb --- /dev/null +++ b/end2end/package-lock.json @@ -0,0 +1,167 @@ +{ + "name": "end2end", + "version": "1.0.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "end2end", + "version": "1.0.0", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.44.1", + "@types/node": "^20.12.12", + "typescript": "^5.4.5" + } + }, + "node_modules/@playwright/test": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/playwright": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.44.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true, + "license": "MIT" + } + }, + "dependencies": { + "@playwright/test": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.44.1.tgz", + "integrity": "sha512-1hZ4TNvD5z9VuhNJ/walIjvMVvYkZKf71axoF/uiAqpntQJXpG64dlXhoDXE3OczPuTuvjf/M5KWFg5VAVUS3Q==", + "dev": true, + "requires": { + "playwright": "1.44.1" + } + }, + "@types/node": { + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", + "dev": true, + "requires": { + "undici-types": "~5.26.4" + } + }, + "fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "optional": true + }, + "playwright": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.44.1.tgz", + "integrity": "sha512-qr/0UJ5CFAtloI3avF95Y0L1xQo6r3LQArLIg/z/PoGJ6xa+EwzrwO5lpNr/09STxdHuUoP2mvuELJS+hLdtgg==", + "dev": true, + "requires": { + "fsevents": "2.3.2", + "playwright-core": "1.44.1" + } + }, + "playwright-core": { + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.44.1.tgz", + "integrity": "sha512-wh0JWtYTrhv1+OSsLPgFzGzt67Y7BE/ZS3jEqgGBlp2ppp1ZDj8c+9IARNW4dwf1poq5MgHreEM2KV/GuR4cFA==", + "dev": true + }, + "typescript": { + "version": "5.4.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.5.tgz", + "integrity": "sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==", + "dev": true + }, + "undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "dev": true + } + } +} diff --git a/end2end/package.json b/end2end/package.json new file mode 100644 index 0000000..a80ac59 --- /dev/null +++ b/end2end/package.json @@ -0,0 +1,15 @@ +{ + "name": "end2end", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": {}, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@playwright/test": "^1.44.1", + "@types/node": "^20.12.12", + "typescript": "^5.4.5" + } +} diff --git a/end2end/playwright.config.ts b/end2end/playwright.config.ts new file mode 100644 index 0000000..aee2d46 --- /dev/null +++ b/end2end/playwright.config.ts @@ -0,0 +1,105 @@ +import type { PlaywrightTestConfig } from "@playwright/test"; +import { devices, defineConfig } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +export default defineConfig({ + testDir: "./tests", + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Configure projects for major browsers */ + projects: [ + { + name: "chromium", + use: { + ...devices["Desktop Chrome"], + }, + }, + + { + name: "firefox", + use: { + ...devices["Desktop Firefox"], + }, + }, + + { + name: "webkit", + use: { + ...devices["Desktop Safari"], + }, + }, + + /* Test against mobile viewports. */ + // { + // name: 'Mobile Chrome', + // use: { + // ...devices['Pixel 5'], + // }, + // }, + // { + // name: 'Mobile Safari', + // use: { + // ...devices['iPhone 12'], + // }, + // }, + + /* Test against branded browsers. */ + // { + // name: 'Microsoft Edge', + // use: { + // channel: 'msedge', + // }, + // }, + // { + // name: 'Google Chrome', + // use: { + // channel: 'chrome', + // }, + // }, + ], + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // port: 3000, + // }, +}); diff --git a/end2end/tests/example.spec.ts b/end2end/tests/example.spec.ts new file mode 100644 index 0000000..0139fc3 --- /dev/null +++ b/end2end/tests/example.spec.ts @@ -0,0 +1,9 @@ +import { test, expect } from "@playwright/test"; + +test("homepage has title and heading text", async ({ page }) => { + await page.goto("http://localhost:3000/"); + + await expect(page).toHaveTitle("Welcome to Leptos"); + + await expect(page.locator("h1")).toHaveText("Welcome to Leptos!"); +}); diff --git a/end2end/tsconfig.json b/end2end/tsconfig.json new file mode 100644 index 0000000..e075f97 --- /dev/null +++ b/end2end/tsconfig.json @@ -0,0 +1,109 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es2016", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + // "jsx": "preserve", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for legacy experimental decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "commonjs", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + // "moduleResolution": "node10", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + // "allowImportingTsExtensions": true, /* Allow imports to include TypeScript file extensions. Requires '--moduleResolution bundler' and either '--noEmit' or '--emitDeclarationOnly' to be set. */ + // "resolvePackageJsonExports": true, /* Use the package.json 'exports' field when resolving package imports. */ + // "resolvePackageJsonImports": true, /* Use the package.json 'imports' field when resolving imports. */ + // "customConditions": [], /* Conditions to set in addition to the resolver-specific defaults when resolving imports. */ + // "resolveJsonModule": true, /* Enable importing .json files. */ + // "allowArbitraryExtensions": true, /* Enable importing files with any extension, provided a declaration file is present. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + // "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + // "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + // "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "verbatimModuleSyntax": true, /* Do not transform or elide any imports or exports not marked as type-only, ensuring they are written in the output file's format based on the 'module' setting. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* Type Checking */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ + // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/nixpacks.toml b/nixpacks.toml new file mode 100644 index 0000000..b5a142d --- /dev/null +++ b/nixpacks.toml @@ -0,0 +1,13 @@ +[phases.install] +# nixPkgs = ['cargo-leptos'] +# cmds = ['cargo install -f wasm-bindgen-cli --version 0.2.93'] +cmds = ['cargo install cargo-quickinstall', 'cargo quickinstall cargo-leptos'] +# cmds = ['rustup target add wasm32-unknown-unknown'] + +[phases.build] +dependsOn = ['install'] +cmds = ['cargo leptos build --release', 'cp -r target build'] +# cmds = ['PATH=":$HOME/.cargo/bin:$PATH" cargo leptos build --release', 'cp -r target build'] + +# [start] +# cmd = './build/release/tanguy-gerome-fi' diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..690cf40ec423dcdb86d042d6ff85bb501ac89dc3 GIT binary patch literal 25487 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 SXH impl IntoView { + // Provides context that manages stylesheets, titles, meta tags, etc. + provide_meta_context(); + + view! { + + + + + + // id=leptos means cargo-leptos will hot-reload this stylesheet + + + + + <Router fallback=|| { + let mut outside_errors = Errors::default(); + outside_errors.insert_with_default_key(AppError::NotFound); + view! { + <ErrorTemplate outside_errors/> + } + .into_view() + }> + <Header/> + <Routes> + <Route path="" view=HomePage/> + </Routes> + <Footer/> + </Router> + } +} + +#[component] +fn Header() -> impl IntoView { + view! { + <header> + <div class="text"> + <h1><span>tanguy</span><wbr/><span>.gerome</span><span>.fi</span></h1> + <div class="links"> + </div> + </div> + <img + class="image" + src="https://images.ctfassets.net/e3magj9g6dp1/14q5L7K0BCol1gx0aCSCck/d1f69bfa404efed6a2dcc71401bbc16d/P5310039-1-2.jpg?w=2000&q=90&fm=avif" + alt="" + /> + </header> + } +} + +#[component] +fn Footer() -> impl IntoView { + view! { + <footer> + <div class="name-and-links main-width"> + <span class="name">Tanguy Gérôme</span> + <div class="links"> + <a href="https://www.instagram.com/kapno.cc/" target="_blank" rel="noopener noreferrer">instagram @kapno.cc</a> + <a href="https://github.com/kapnoc" target="_blank" rel="noopener noreferrer">github @kapnoc</a> + <a href="mailto:tanguy@gerome.fi" target="_blank" rel="noopener noreferrer">email tanguy@gerome.fi</a> + </div> + </div> + </footer> + } +} + +#[component] +fn HomePage() -> impl IntoView { + view! { + <main class="main-width"> + <h1>"Welcome!"</h1> + <p>"This website is under construction, please check back later :)"</p> + </main> + } +} diff --git a/src/error_template.rs b/src/error_template.rs new file mode 100644 index 0000000..1e0508d --- /dev/null +++ b/src/error_template.rs @@ -0,0 +1,72 @@ +use http::status::StatusCode; +use leptos::*; +use thiserror::Error; + +#[derive(Clone, Debug, Error)] +pub enum AppError { + #[error("Not Found")] + NotFound, +} + +impl AppError { + pub fn status_code(&self) -> StatusCode { + match self { + AppError::NotFound => StatusCode::NOT_FOUND, + } + } +} + +// A basic function to display errors served by the error boundaries. +// Feel free to do more complicated things here than just displaying the error. +#[component] +pub fn ErrorTemplate( + #[prop(optional)] outside_errors: Option<Errors>, + #[prop(optional)] errors: Option<RwSignal<Errors>>, +) -> impl IntoView { + let errors = match outside_errors { + Some(e) => create_rw_signal(e), + None => match errors { + Some(e) => e, + None => panic!("No Errors found and we expected errors!"), + }, + }; + // Get Errors from Signal + let errors = errors.get_untracked(); + + // Downcast lets us take a type that implements `std::error::Error` + let errors: Vec<AppError> = errors + .into_iter() + .filter_map(|(_k, v)| v.downcast_ref::<AppError>().cloned()) + .collect(); + println!("Errors: {errors:#?}"); + + // Only the response code for the first error is actually sent from the server + // this may be customized by the specific application + #[cfg(feature = "ssr")] + { + use leptos_axum::ResponseOptions; + let response = use_context::<ResponseOptions>(); + if let Some(response) = response { + response.set_status(errors[0].status_code()); + } + } + + view! { + <h1>{if errors.len() > 1 {"Errors"} else {"Error"}}</h1> + <For + // a function that returns the items we're iterating over; a signal is fine + each= move || {errors.clone().into_iter().enumerate()} + // a unique key for each item as a reference + key=|(index, _error)| *index + // renders each item to a view + children=move |error| { + let error_string = error.1.to_string(); + let error_code= error.1.status_code(); + view! { + <h2>{error_code.to_string()}</h2> + <p>"Error: " {error_string}</p> + } + } + /> + } +} diff --git a/src/fileserv.rs b/src/fileserv.rs new file mode 100644 index 0000000..a499201 --- /dev/null +++ b/src/fileserv.rs @@ -0,0 +1,60 @@ +use crate::app::App; +use axum::response::Response as AxumResponse; +use axum::{ + body::Body, + extract::State, + http::{Request, Response, StatusCode}, + response::IntoResponse, +}; +use leptos::*; +use tower::ServiceExt; +use tower_http::services::ServeDir; + +pub async fn file_and_error_handler( + State(options): State<LeptosOptions>, + req: Request<Body>, +) -> AxumResponse { + let root = options.site_root.clone(); + let (parts, body) = req.into_parts(); + + let mut static_parts = parts.clone(); + static_parts.headers.clear(); + if let Some(encodings) = parts.headers.get("accept-encoding") { + static_parts + .headers + .insert("accept-encoding", encodings.clone()); + } + + let res = get_static_file(Request::from_parts(static_parts, Body::empty()), &root) + .await + .unwrap(); + + if res.status() == StatusCode::OK { + res.into_response() + } else { + let handler = leptos_axum::render_app_to_stream(options.to_owned(), App); + handler(Request::from_parts(parts, body)) + .await + .into_response() + } +} + +async fn get_static_file( + request: Request<Body>, + root: &str, +) -> Result<Response<Body>, (StatusCode, String)> { + // `ServeDir` implements `tower::Service` so we can call it with `tower::ServiceExt::oneshot` + // This path is relative to the cargo root + match ServeDir::new(root) + .precompressed_gzip() + .precompressed_br() + .oneshot(request) + .await + { + Ok(res) => Ok(res.into_response()), + Err(err) => Err(( + StatusCode::INTERNAL_SERVER_ERROR, + format!("Error serving files: {err}"), + )), + } +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..ac36687 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,12 @@ +pub mod app; +pub mod error_template; +#[cfg(feature = "ssr")] +pub mod fileserv; + +#[cfg(feature = "hydrate")] +#[wasm_bindgen::prelude::wasm_bindgen] +pub fn hydrate() { + use crate::app::*; + console_error_panic_hook::set_once(); + leptos::mount_to_body(App); +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..774909f --- /dev/null +++ b/src/main.rs @@ -0,0 +1,38 @@ +#[cfg(feature = "ssr")] +#[tokio::main] +async fn main() { + use axum::Router; + use leptos::*; + use leptos_axum::{generate_route_list, LeptosRoutes}; + use tanguy_gerome_fi::app::*; + use tanguy_gerome_fi::fileserv::file_and_error_handler; + + // Setting get_configuration(None) means we'll be using cargo-leptos's env values + // For deployment these variables are: + // <https://github.com/leptos-rs/start-axum#executing-a-server-on-a-remote-machine-without-the-toolchain> + // Alternately a file can be specified such as Some("Cargo.toml") + // The file would need to be included with the executable when moved to deployment + let conf = get_configuration(None).await.unwrap(); + let leptos_options = conf.leptos_options; + let addr = leptos_options.site_addr; + let routes = generate_route_list(App); + + // build our application with a route + let app = Router::new() + .leptos_routes(&leptos_options, routes, App) + .fallback(file_and_error_handler) + .with_state(leptos_options); + + let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); + logging::log!("listening on http://{}", &addr); + axum::serve(listener, app.into_make_service()) + .await + .unwrap(); +} + +#[cfg(not(feature = "ssr"))] +pub fn main() { + // no client-side main function + // unless we want this to work with e.g., Trunk for a purely client-side app + // see lib.rs for hydration function instead +} diff --git a/style/main.scss b/style/main.scss new file mode 100644 index 0000000..0be78b1 --- /dev/null +++ b/style/main.scss @@ -0,0 +1,154 @@ +$mainGreen: #2E7D32; +$mainGrey: #0F0F0F; + +@mixin top-level-padding { + padding: 0 16px; + @media all and (max-width: 400px) { + padding: 0 8px; + } +} + +* { + box-sizing: border-box; +} + +body { + font-family: 'Ubuntu', sans-serif; + text-align: left; + font-weight: 300; + font-size: 16px; + + background: white; + color: $mainGrey; + + display: flex; + height: 100%; + min-height: 100vh; + flex-direction: column; + align-items: center; + justify-content: space-between; + margin: 0; + + .main-width { + width: 100%; + max-width: 800px; + } + + h1, h2, h3, h4, h5, h6 { + font-family: "Roboto Slab", serif; + font-weight: 300; + } + h1 { font-size: 42px; } + h2 { font-size: 32px; } + h3 { font-size: 22px; } + h4 { font-size: 18px; } + + header { + background: $mainGrey; + color: white; + + width: 100%; + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + + @media all and (max-width: 2000px) { + justify-content: flex-end; + } + + @media all and (max-width: 800px) { + flex-direction: column; + align-items: stretch; + } + + .text { + @include top-level-padding; + flex-basis: auto; + flex-shrink: 0; + flex-grow: 1; + + display: flex; + flex-direction: row; + align-items: center; + justify-content: center; + gap: 16px; + + h1 { + display: flex; + flex-direction: column; + align-items: flex-start; + } + + .links { + display: flex; + flex-direction: column; + align-items: flex-end; + } + } + + .image { + max-width: 800px; + width: 100%; + max-height: 300px; + height: 100%; + object-fit: cover; + object-position: top; + flex-shrink: 1; + } + } + + main { + @include top-level-padding; + } + + footer { + background: $mainGrey; + color: white; + + order: 100; + + width: 100%; + display: flex; + align-items: center; + justify-content: center; + padding: 10px 0; + + .name-and-links { + @include top-level-padding; + flex-grow: 1; + + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + gap: 8px; + + @media all and (max-width: 400px) { + flex-direction: column; + align-items: stretch; + } + + .name { + } + + .links { + display: flex; + flex-direction: row; + gap: 32px; + + @media all and (max-width: 800px) { + gap: 8px; + flex-direction: column; + text-align: right; + } + + a { + color: white!important; + text-decoration: unset; + } + } + } + } + +}