This commit is contained in:
2025-02-04 16:27:38 +01:00
parent 51ada6c9bd
commit 73abd96f10
7 changed files with 319 additions and 142 deletions

163
Cargo.lock generated
View File

@@ -124,6 +124,7 @@ dependencies = [
"camino", "camino",
"chrono", "chrono",
"clap", "clap",
"codee",
"confik", "confik",
"console_error_panic_hook", "console_error_panic_hook",
"derive_more", "derive_more",
@@ -166,9 +167,9 @@ dependencies = [
[[package]] [[package]]
name = "async-trait" name = "async-trait"
version = "0.1.85" version = "0.1.86"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f934833b4b7233644e5848f235df3f57ed8c80f1528a26c3dfa13d2147fa056" checksum = "644dd749086bf3771a2fbc5f256fdb982d53f011c7d5d560304eafeecebce79d"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -314,9 +315,9 @@ dependencies = [
[[package]] [[package]]
name = "bumpalo" name = "bumpalo"
version = "3.16.0" version = "3.17.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf"
[[package]] [[package]]
name = "byteorder" name = "byteorder"
@@ -326,9 +327,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.9.0" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b" checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9"
[[package]] [[package]]
name = "camino" name = "camino"
@@ -341,9 +342,9 @@ dependencies = [
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.10" version = "1.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13208fcbb66eaeffe09b99fffbe1af420f00a7b35aa99ad683dfc1aa76145229" checksum = "e4730490333d58093109dc02c23174c3f4d490998c3fed3cc8e82d57afedb9cf"
dependencies = [ dependencies = [
"shlex", "shlex",
] ]
@@ -398,9 +399,9 @@ dependencies = [
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.5.27" version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "769b0145982b4b48713e01ec42d61614425f27b7058bda7180a3a41f30104796" checksum = "3e77c3243bd94243c03672cb5154667347c457ca271254724f9f393aee1c05ff"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
"clap_derive", "clap_derive",
@@ -420,9 +421,9 @@ dependencies = [
[[package]] [[package]]
name = "clap_derive" name = "clap_derive"
version = "4.5.24" version = "4.5.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "54b755194d6389280185988721fffba69495eed5ee9feeee9a599b53db80318c" checksum = "bf4ced95c6f4a675af3da73304b9ac4ed991640c36374e4b46795c49e17cf1ed"
dependencies = [ dependencies = [
"heck", "heck",
"proc-macro2", "proc-macro2",
@@ -438,13 +439,13 @@ checksum = "f46ad14479a25103f283c0f10005961cf086d8dc42205bb44c46ac563475dca6"
[[package]] [[package]]
name = "codee" name = "codee"
version = "0.2.0" version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d3ad3122b0001c7f140cf4d605ef9a9e2c24d96ab0b4fb4347b76de2425f445" checksum = "0f18d705321923b1a9358e3fc3c57c3b50171196827fc7f5f10b053242aca627"
dependencies = [ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"thiserror 1.0.69", "thiserror 2.0.11",
] ]
[[package]] [[package]]
@@ -669,6 +670,12 @@ version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408" checksum = "669a445ee724c5c69b1b06fe0b63e70a1c84bc9bb7d9696cd4f4e3ec45050408"
[[package]]
name = "dyn-clone"
version = "1.0.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35"
[[package]] [[package]]
name = "either" name = "either"
version = "1.13.0" version = "1.13.0"
@@ -677,10 +684,11 @@ checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0"
[[package]] [[package]]
name = "either_of" name = "either_of"
version = "0.1.2" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2dc0006c5cf511f802ddcffc0a6df9dcc1912f5f0e448f6641b3b035f14f43d" checksum = "169ae1dd00fb612cf27fd069b3b10f325ea60ac551f08e5b931b4413972a847d"
dependencies = [ dependencies = [
"paste",
"pin-project-lite", "pin-project-lite",
] ]
@@ -1162,9 +1170,9 @@ checksum = "9171a2ea8a68358193d15dd5d70c1c10a2afc3e7e4c5bc92bc9f025cebd7359c"
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.9.5" version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@@ -1190,9 +1198,9 @@ dependencies = [
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "1.5.2" version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "256fb8d4bd6413123cc9d91832d78325c48ff41677595be797d90f42969beae0" checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@@ -1409,9 +1417,9 @@ checksum = "71dd52191aae121e8611f1e8dc3e324dd0dd1dee1e6dd91d10ee07a3cfb4d9d8"
[[package]] [[package]]
name = "inventory" name = "inventory"
version = "0.3.17" version = "0.3.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b31349d02fe60f80bbbab1a9402364cad7460626d6030494b08ac4a2075bf81" checksum = "54b12ebb6799019b044deaf431eadfe23245b259bba5a2c0796acec3943a3cdb"
dependencies = [ dependencies = [
"rustversion", "rustversion",
] ]
@@ -1455,9 +1463,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
[[package]] [[package]]
name = "leptos" name = "leptos"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "21c31c9d022c77702c53e02830d08b28320aca9c0899a19c443096c114623fa5" checksum = "78329c12843d64766d8f00216aae665416d804327302ce8e0ab83884dfa91887"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"base64 0.22.1", "base64 0.22.1",
@@ -1494,9 +1502,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_axum" name = "leptos_axum"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43b613d5784037baee42a11d21bc263adfc1a55e416556a3d5bfe39c7b87fadf" checksum = "d59be1dd90fa5102d0a48696c93328c9947aaef19f2dbe9c81f819db3b11a849"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"axum", "axum",
@@ -1518,9 +1526,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_config" name = "leptos_config"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d874993c7664d757677d056c8f46b5cb5365fe622005e1bf26050f4996e7e52" checksum = "132a18e8ffc4fbe2d624f3743d88a1b4989bff2d5e12be2b0d2749201d9dfb52"
dependencies = [ dependencies = [
"config", "config",
"regex", "regex",
@@ -1531,9 +1539,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_dom" name = "leptos_dom"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a462aaeec85bc4ecfb26bf324437b92690bf3add1e30eb29b3acc08b20e8b4cb" checksum = "d468f638f2f13d70d99d9952be98d671a75366034472f3828e586ba62d770049"
dependencies = [ dependencies = [
"js-sys", "js-sys",
"or_poisoned", "or_poisoned",
@@ -1547,9 +1555,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_hot_reload" name = "leptos_hot_reload"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "07eb295ad2f3b2af190da62af339b84fd01ce3c71702f09eb69a57310fcf0c6d" checksum = "8ba37d76693fc6228554e0bb06a9aa41c59e2b5180caf423c7913557b81d01dd"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"camino", "camino",
@@ -1565,9 +1573,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_integration_utils" name = "leptos_integration_utils"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8652fcd7a1744f85403b95c5520143f3b962d640c8450b8514f9530fb5c4b76" checksum = "123887e1b34f8fadab385b3192e14a4e5bd84505dec16c31de0b8c4ccc8553d3"
dependencies = [ dependencies = [
"futures", "futures",
"hydration_context", "hydration_context",
@@ -1580,9 +1588,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_macro" name = "leptos_macro"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "90291b25ee576bc9c299d3371cc8f09bf60ea939a8de61fa8b744650aff76e24" checksum = "064d0c8b144b93f8d7e84b30c16d1da0e64a63c7e91b9a872f7be63601c5868b"
dependencies = [ dependencies = [
"attribute-derive", "attribute-derive",
"cfg-if", "cfg-if",
@@ -1603,9 +1611,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_meta" name = "leptos_meta"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7250991b2077ef5869e999c74cf4990926a3c3919b50c9937e101c1c874102db" checksum = "3abd2ac7fbfeee757fd569f7db4bdbaafe1e899049435476f06d4be1911f6097"
dependencies = [ dependencies = [
"futures", "futures",
"indexmap", "indexmap",
@@ -1619,9 +1627,9 @@ dependencies = [
[[package]] [[package]]
name = "leptos_router" name = "leptos_router"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9a193dbd62b9617a5d7d199ea70c570da01a1bbe798e617373b6351845be6778" checksum = "8dbc548cc4d127608a79354361df357f53c7d8e89dc14ef9738d789cd338694a"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"either_of", "either_of",
@@ -1644,20 +1652,21 @@ dependencies = [
[[package]] [[package]]
name = "leptos_router_macro" name = "leptos_router_macro"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "34bc3f80ad810b22058f12d278bb0bf929779cc0bc1289a06980d896f62743f0" checksum = "3010b3a222b5ff3d16421d074f74b52049df4353330373d17f675b2e0f51c9de"
dependencies = [ dependencies = [
"proc-macro-error2", "proc-macro-error2",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn",
] ]
[[package]] [[package]]
name = "leptos_server" name = "leptos_server"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "18caffe32c245ddb35697edd898ccb3393efce67672a707a14eebd0db2e8249a" checksum = "fb1779f1f0570915066c132fb11f999add8b13d02ca5221735193eb02b3fa69a"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"base64 0.22.1", "base64 0.22.1",
@@ -1953,18 +1962,18 @@ checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e"
[[package]] [[package]]
name = "pin-project" name = "pin-project"
version = "1.1.8" version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e2ec53ad785f4d35dac0adea7f7dc6f1bb277ad84a680c7afefeae05d1f5916" checksum = "dfe2e71e1471fe07709406bf725f710b02927c9c54b2b5b2ec0e8087d97c327d"
dependencies = [ dependencies = [
"pin-project-internal", "pin-project-internal",
] ]
[[package]] [[package]]
name = "pin-project-internal" name = "pin-project-internal"
version = "1.1.8" version = "1.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d56a66c0c55993aa927429d0f8a0abfd74f084e4d9c192cffed01e418d83eefb" checksum = "f6e859e6e5bd50440ab63c47e3ebabc90f26251f7c73c3d3e837b74a1cc3fa67"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2120,9 +2129,9 @@ dependencies = [
[[package]] [[package]]
name = "reactive_graph" name = "reactive_graph"
version = "0.1.4" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fbf210c04505e128fb7f64acecc23c71f82f56c7d481b190e1010b7bada2cb9" checksum = "059aede5acae8f5c25b1d34b6df34700006418b3c493db3698b7ebcd4a8a6287"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"async-lock", "async-lock",
@@ -2142,9 +2151,9 @@ dependencies = [
[[package]] [[package]]
name = "reactive_stores" name = "reactive_stores"
version = "0.1.3" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "80bb1913eeb71f74028213455ee971550c2b3cb91b6acd5efa8a0f8dc59f5039" checksum = "4c7edacf4298579a5772285b8e2dc0b9953c8fbaa9c3f56c3dd69d56e5af7a48"
dependencies = [ dependencies = [
"guardian", "guardian",
"itertools", "itertools",
@@ -2157,9 +2166,9 @@ dependencies = [
[[package]] [[package]]
name = "reactive_stores_macro" name = "reactive_stores_macro"
version = "0.1.0" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d86e4f08f361b05d11422398cef4bc4cf356f2fdd2f06a96646b0e9cd902226" checksum = "178b1cd8b2871a45bfc8e13ff8076049b6e9a5132e72414e5cab3894c4a6adb3"
dependencies = [ dependencies = [
"convert_case", "convert_case",
"proc-macro-error2", "proc-macro-error2",
@@ -2277,9 +2286,9 @@ checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4"
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.18" version = "1.0.19"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd"
[[package]] [[package]]
name = "same-file" name = "same-file"
@@ -2338,9 +2347,9 @@ dependencies = [
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.137" version = "1.0.138"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "930cfb6e6abf99298aaad7d29abbef7a9999a9a8806a40088f55f0dcec03146b" checksum = "d434192e7da787e94a6ea7e9670b26a036d0ca41e0b7efb2676dd32bae872949"
dependencies = [ dependencies = [
"itoa", "itoa",
"memchr", "memchr",
@@ -2392,9 +2401,9 @@ dependencies = [
[[package]] [[package]]
name = "server_fn" name = "server_fn"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f5dd7fcccd3ef2081da086c1f8595b506627abbbbc9f64be0141d2251219570e" checksum = "5c183c31152fd00e994a3ea0ca43e6017056ccf7812160b0ae008acc3de8241c"
dependencies = [ dependencies = [
"axum", "axum",
"bytes", "bytes",
@@ -2429,9 +2438,9 @@ dependencies = [
[[package]] [[package]]
name = "server_fn_macro" name = "server_fn_macro"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e0bbac4f01a714b0490247ac625bdb7055548210556c39e8f56a2dbbe3abc70b" checksum = "c43b2266308c118be1a1cc60602f8efb07a64e72deed8d317704d5cfda092ca1"
dependencies = [ dependencies = [
"const_format", "const_format",
"convert_case", "convert_case",
@@ -2443,9 +2452,9 @@ dependencies = [
[[package]] [[package]]
name = "server_fn_macro_default" name = "server_fn_macro_default"
version = "0.7.4" version = "0.7.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f07dfd1744a5f5612f00f69fe035b0bfafdf12bb46d76e785673078a9e56b170" checksum = "087eca61bc8f93d868b8c10ca058da358fd7aaeb7bc8415b572f9f3f27ce0b93"
dependencies = [ dependencies = [
"server_fn_macro", "server_fn_macro",
"syn", "syn",
@@ -2531,9 +2540,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.96" version = "2.0.98"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d5d0adab1ae378d7f53bdebc67a39f1f151407ef230f0ce2883572f5d8985c80" checksum = "36147f1a48ae0ec2b5b3bc5b537d267457555a10dc06f3dbc8cb11ba3006d3b1"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -2571,13 +2580,15 @@ dependencies = [
[[package]] [[package]]
name = "tachys" name = "tachys"
version = "0.1.4" version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d777e4426a597296b020edcb5c3d8f25a3ccd8adfd22eb5154ac81da946aef9f" checksum = "59a3bbcf8e3b52cad5f0aa860837d4d1796c7c4873b083c9520a1bbba4747973"
dependencies = [ dependencies = [
"any_spawner", "any_spawner",
"async-trait",
"const_str_slice_concat", "const_str_slice_concat",
"drain_filter_polyfill", "drain_filter_polyfill",
"dyn-clone",
"either_of", "either_of",
"futures", "futures",
"html-escape", "html-escape",
@@ -2734,9 +2745,9 @@ dependencies = [
[[package]] [[package]]
name = "toml_edit" name = "toml_edit"
version = "0.22.22" version = "0.22.23"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" checksum = "02a8b472d1a3d7c18e2d61a489aee3453fd9031c33e4f55bd533f4a7adca1bee"
dependencies = [ dependencies = [
"indexmap", "indexmap",
"serde", "serde",
@@ -2944,9 +2955,9 @@ checksum = "75b844d17643ee918803943289730bec8aac480150456169e647ed0b576ba539"
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.14" version = "1.0.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
@@ -3145,7 +3156,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@@ -3247,9 +3258,9 @@ checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
[[package]] [[package]]
name = "winnow" name = "winnow"
version = "0.6.24" version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8d71a593cc5c42ad7876e2c1fda56f314f3754c084128833e64f1345ff8a03a" checksum = "86e376c75f4f43f44db463cf729e0d3acbf954d13e22c51e26e4c264b4ab545f"
dependencies = [ dependencies = [
"memchr", "memchr",
] ]

View File

@@ -45,6 +45,8 @@ xdg = { version = "2.5", optional = true }
uuid = { version = "1.12", features = ["serde", "v4"] } uuid = { version = "1.12", features = ["serde", "v4"] }
redb = { version = "2.4", optional = true } redb = { version = "2.4", optional = true }
bincode = { version = "1.3", optional = true } bincode = { version = "1.3", optional = true }
serde_json = { version = "1" }
codee = { version = "0.3" }
[dev-dependencies.serde_json] [dev-dependencies.serde_json]
version = "1" version = "1"

View File

@@ -1,10 +1,11 @@
use crate::codec::ron::RonCodec; use crate::codec::ron::RonEncoded;
use crate::models; use crate::models;
use crate::pages; use crate::pages;
use leptos::prelude::*; use leptos::prelude::*;
use leptos_router::components::*; use leptos_router::components::*;
use leptos_router::path; use leptos_router::path;
use std::sync::Arc; use std::sync::Arc;
use type_toppings::ResultExt;
pub fn shell(options: LeptosOptions) -> impl IntoView { pub fn shell(options: LeptosOptions) -> impl IntoView {
use leptos_meta::MetaTags; use leptos_meta::MetaTags;
@@ -60,7 +61,13 @@ pub fn Home() -> impl leptos::IntoView {
let action = Action::new(|()| async move { let action = Action::new(|()| async move {
tracing::debug!("running action"); tracing::debug!("running action");
let walls = get_walls().await.unwrap().into_inner(); let walls = get_walls()
.await
.inspect_err(|e| {
dbg!(e);
})
.expect("failed to get walls")
.into_inner();
let wall = walls.first(); let wall = walls.first();
if let Some(wall) = wall { if let Some(wall) = wall {
@@ -81,7 +88,7 @@ pub fn Home() -> impl leptos::IntoView {
#[server] #[server]
#[tracing::instrument(skip_all, err)] #[tracing::instrument(skip_all, err)]
async fn get_walls() -> Result<RonCodec<Vec<models::Wall>>, ServerFnError> { async fn get_walls() -> Result<RonEncoded<Vec<models::Wall>>, ServerFnError> {
use redb::ReadableTable; use redb::ReadableTable;
tracing::debug!("get walls"); tracing::debug!("get walls");
@@ -104,5 +111,5 @@ async fn get_walls() -> Result<RonCodec<Vec<models::Wall>>, ServerFnError> {
}) })
.await??; .await??;
Ok(RonCodec::new(walls)) Ok(RonEncoded::new(walls))
} }

View File

@@ -1,59 +1,159 @@
pub mod ron { pub mod ron {
//! Wrap T in RonCodec<T> that when serialized, always serializes to a [ron] string. //! Wrap T in RonCodec<T> that when serialized, always serializes to a [ron] string.
#[derive(Debug, Clone)] use codee::Decoder;
pub struct RonCodec<T> { use codee::Encoder;
t: T, use serde::Deserialize;
use serde::Serialize;
use serde::de::DeserializeOwned;
use server_fn::ServerFnError;
use server_fn::codec::Encoding;
use server_fn::codec::FromReq;
use server_fn::codec::FromRes;
use server_fn::codec::IntoReq;
use server_fn::codec::IntoRes;
use server_fn::request::ClientReq;
use server_fn::request::Req;
use server_fn::response::ClientRes;
use server_fn::response::Res;
pub struct Ron;
impl<T> Encoder<T> for Ron
where
T: Serialize,
{
type Encoded = String;
type Error = ron::Error;
fn encode(val: &T) -> Result<Self::Encoded, Self::Error> {
ron::to_string(val)
}
} }
impl<T> RonCodec<T> { impl<T> Decoder<T> for Ron
where
for<'de> T: Deserialize<'de>,
{
type Encoded = str;
type Error = ron::error::SpannedError;
fn decode(val: &Self::Encoded) -> Result<T, Self::Error> {
ron::from_str(val)
}
}
impl Encoding for Ron {
const CONTENT_TYPE: &'static str = "application/ron";
const METHOD: http::Method = http::Method::POST;
}
#[derive(Debug, Clone)]
pub struct RonEncoded<T>(pub T);
impl<T> RonEncoded<T> {
pub fn into_inner(self) -> T { pub fn into_inner(self) -> T {
self.t self.0
} }
pub fn new(t: T) -> Self { pub fn new(t: T) -> Self {
Self { t } Self(t)
} }
} }
impl<T> std::ops::Deref for RonCodec<T> { impl<T> std::ops::Deref for RonEncoded<T> {
type Target = T; type Target = T;
fn deref(&self) -> &Self::Target { fn deref(&self) -> &Self::Target {
&self.t &self.0
} }
} }
impl<T> serde::Serialize for RonCodec<T> // impl<T> serde::Serialize for RonEncoded<T>
// where
// T: serde::Serialize,
// {
// #[tracing::instrument(skip_all, err)]
// fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
// where
// S: serde::Serializer,
// {
// let serialized = ron::to_string(&self.0).map_err(serde::ser::Error::custom)?;
// serializer.serialize_str(&serialized)
// }
// }
// impl<'de, T> serde::Deserialize<'de> for RonEncoded<T>
// where
// T: serde::de::DeserializeOwned + 'static,
// {
// #[tracing::instrument(skip_all, err)]
// fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
// where
// D: serde::Deserializer<'de>,
// {
// let s = String::deserialize(deserializer)?;
// let t: T = ron::from_str(&s).map_err(serde::de::Error::custom)?;
// Ok(Self(t))
// }
// }
// IntoReq
impl<T, Request, Err> IntoReq<Ron, Request, Err> for RonEncoded<T>
where where
T: serde::Serialize, Request: ClientReq<Err>,
T: Serialize,
{ {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> fn into_req(self, path: &str, accepts: &str) -> Result<Request, ServerFnError<Err>> {
where let data = Ron::encode(&self.0).map_err(|e| ServerFnError::Serialization(e.to_string()))?;
S: serde::Serializer, Request::try_new_post(path, Ron::CONTENT_TYPE, accepts, data)
{
let serialized = ron::to_string(&self.t).map_err(serde::ser::Error::custom)?;
serializer.serialize_str(&serialized)
} }
} }
impl<'de, T> serde::Deserialize<'de> for RonCodec<T> // FromReq
impl<T, Request, Err> FromReq<Ron, Request, Err> for RonEncoded<T>
where where
T: serde::de::DeserializeOwned + 'static, Request: Req<Err> + Send,
T: DeserializeOwned,
{ {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error> async fn from_req(req: Request) -> Result<Self, ServerFnError<Err>> {
where let data = req.try_into_string().await?;
D: serde::Deserializer<'de>, Ron::decode(&data).map(RonEncoded).map_err(|e| ServerFnError::Args(e.to_string()))
{ }
let s = String::deserialize(deserializer)?; }
let t: T = ron::from_str(&s).map_err(serde::de::Error::custom)?;
Ok(Self { t }) // IntoRes
impl<CustErr, T, Response> IntoRes<Ron, Response, CustErr> for RonEncoded<T>
where
Response: Res<CustErr>,
T: Serialize + Send,
{
async fn into_res(self) -> Result<Response, ServerFnError<CustErr>> {
let data = Ron::encode(&self.0).map_err(|e| ServerFnError::Serialization(e.to_string()))?;
Response::try_from_string(Ron::CONTENT_TYPE, data)
}
}
// FromRes
impl<T, Response, Err> FromRes<Ron, Response, Err> for RonEncoded<T>
where
Response: ClientRes<Err> + Send,
T: DeserializeOwned,
{
async fn from_res(res: Response) -> Result<Self, ServerFnError<Err>> {
let data = res.try_into_string().await?;
Ron::decode(&data)
.map(RonEncoded)
.map_err(|e| ServerFnError::Deserialization(e.to_string()))
} }
} }
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::RonCodec; use super::Ron;
use super::RonEncoded;
use codee::Decoder;
use codee::Encoder;
use serde::Deserialize; use serde::Deserialize;
use serde::Serialize; use serde::Serialize;
@@ -63,25 +163,36 @@ pub mod ron {
value: i32, value: i32,
} }
// #[test]
// fn test_ron_wrapper() {
// let original = TestStruct {
// name: "Test".to_string(),
// value: 42,
// };
// // Wrap in RonCodec
// let wrapped = RonEncoded::new(original.clone());
// // Serialize
// let serialized = serde_json::to_string(&wrapped).expect("Serialization failed");
// println!("Serialized: {}", serialized);
// // Deserialize
// let deserialized: RonEncoded<TestStruct> = serde_json::from_str(&serialized).expect("Deserialization failed");
// // Compare
// assert_eq!(deserialized.into_inner(), original);
// }
#[test] #[test]
fn test_ron_codec() { fn test_ron_codec() {
let original = TestStruct { let original = TestStruct {
name: "Test".to_string(), name: "Test".to_string(),
value: 42, value: 42,
}; };
let enc = Ron::encode(&original).unwrap();
// Wrap in RonCodec let dec: TestStruct = Ron::decode(&enc).unwrap();
let wrapped = RonCodec::new(original.clone()); assert_eq!(dec, original);
// Serialize
let serialized = serde_json::to_string(&wrapped).expect("Serialization failed");
println!("Serialized: {}", serialized);
// Deserialize
let deserialized: RonCodec<TestStruct> = serde_json::from_str(&serialized).expect("Deserialization failed");
// Compare
assert_eq!(deserialized.into_inner(), original);
} }
} }
} }

View File

@@ -1,4 +1,4 @@
use crate::codec::ron::RonCodec; use crate::codec::ron::RonEncoded;
use crate::components::header::HeaderItem; use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems; use crate::components::header::HeaderItems;
use crate::components::header::StyledHeader; use crate::components::header::StyledHeader;
@@ -150,7 +150,7 @@ pub struct Image {
} }
#[server] #[server]
async fn load_initial_data() -> Result<RonCodec<InitialData>, ServerFnError> { async fn load_initial_data() -> Result<RonEncoded<InitialData>, ServerFnError> {
todo!() todo!()
// let wall = state.persistent.with(|s| s.wall.clone()).await; // let wall = state.persistent.with(|s| s.wall.clone()).await;
// Ok(RonCodec::new(InitialData { wall })) // Ok(RonCodec::new(InitialData { wall }))

View File

@@ -1,4 +1,4 @@
use crate::codec::ron::RonCodec; use crate::codec::ron::RonEncoded;
use crate::components::header::HeaderItem; use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems; use crate::components::header::HeaderItems;
use crate::components::header::StyledHeader; use crate::components::header::StyledHeader;
@@ -63,7 +63,7 @@ pub struct InitialData {
} }
#[server] #[server]
async fn load_initial_data() -> Result<RonCodec<InitialData>, ServerFnError> { async fn load_initial_data() -> Result<RonEncoded<InitialData>, ServerFnError> {
todo!() todo!()
// let state = expect_context::<State>(); // let state = expect_context::<State>();

View File

@@ -1,10 +1,12 @@
use crate::codec::ron::RonCodec; use crate::codec::ron::Ron;
use crate::codec::ron::RonEncoded;
use crate::components::button::Button; use crate::components::button::Button;
use crate::components::header::HeaderItem; use crate::components::header::HeaderItem;
use crate::components::header::HeaderItems; use crate::components::header::HeaderItems;
use crate::components::header::StyledHeader; use crate::components::header::StyledHeader;
use crate::models; use crate::models;
use crate::models::HoldRole; use crate::models::HoldRole;
use crate::models::WallUid;
use leptos::Params; use leptos::Params;
use leptos::prelude::*; use leptos::prelude::*;
use leptos::reactive::graph::ReactiveNode; use leptos::reactive::graph::ReactiveNode;
@@ -17,21 +19,37 @@ struct WallParams {
} }
#[component] #[component]
#[tracing::instrument(skip_all)]
pub fn Wall() -> impl leptos::IntoView { pub fn Wall() -> impl leptos::IntoView {
tracing::debug!("Enter");
let params = leptos_router::hooks::use_params::<WallParams>(); let params = leptos_router::hooks::use_params::<WallParams>();
let wall = Resource::new( // TODO
let wall = Resource::<models::Wall, Ron>::new_with_options(
move || params.get().unwrap().id, move || params.get().unwrap().id,
move |wall_id| async move { {
if let Some(wall_id) = wall_id { move |wall_uid: Option<WallUid>| async move {
let wall = get_wall(wall_id).await.unwrap().into_inner(); let wall_uid = wall_uid.unwrap();
Some(wall) let wall = get_wall(wall_uid).await.unwrap().into_inner();
} else { wall
None
} }
}, },
false,
); );
// // TODO
// let wall = Resource::new(
// move || params.get().unwrap().id,
// move |wall_id| async move {
// if let Some(wall_id) = wall_id {
// let wall = get_wall(wall_id).await.unwrap();
// Some(wall)
// } else {
// None
// }
// },
// );
let header_items = HeaderItems { let header_items = HeaderItems {
left: vec![], left: vec![],
middle: vec![HeaderItem { middle: vec![HeaderItem {
@@ -57,10 +75,10 @@ pub fn Wall() -> impl leptos::IntoView {
<div class="m-2"> <div class="m-2">
<Suspense fallback=move || view! {<p>"Loading..."</p>}> <Suspense fallback=move || view! {<p>"Loading..."</p>}>
{move || Suspend::new(async move{ {move || Suspend::new(async move{
let wall: Option<Option<models::Wall>> = wall.get(); let wall: Option<Option<RonEncoded<models::Wall>>> = wall.get();
wall.map(|wall|{let wall = wall.unwrap(); wall.map(|wall|{let wall = wall.unwrap();
view! { view! {
<Ready wall /> <Ready wall=wall.into_inner() />
} }
}) })
})} })}
@@ -95,6 +113,7 @@ fn Ready(wall: models::Wall) -> impl leptos::IntoView {
let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-3", wall.rows, wall.cols); let grid_classes = format!("grid grid-rows-{} grid-cols-{} gap-3", wall.rows, wall.cols);
tracing::debug!("view");
view! { view! {
<div class="grid grid-cols-[auto,1fr] gap-8"> <div class="grid grid-cols-[auto,1fr] gap-8">
// Render the wall // Render the wall
@@ -114,7 +133,9 @@ fn Ready(wall: models::Wall) -> impl leptos::IntoView {
} }
#[component] #[component]
#[tracing::instrument(skip_all)]
fn Hold(hold: models::Hold, #[prop(into)] role: Signal<Option<HoldRole>>) -> impl leptos::IntoView { fn Hold(hold: models::Hold, #[prop(into)] role: Signal<Option<HoldRole>>) -> impl leptos::IntoView {
tracing::trace!("Enter");
let class = move || { let class = move || {
let role_classes = match role.get() { let role_classes = match role.get() {
Some(HoldRole::Start) => Some("outline outline-offset-2 outline-green-500"), Some(HoldRole::Start) => Some("outline outline-offset-2 outline-green-500"),
@@ -137,13 +158,18 @@ fn Hold(hold: models::Hold, #[prop(into)] role: Signal<Option<HoldRole>>) -> imp
view! { <img class="object-cover w-full h-full" src=src /> } view! { <img class="object-cover w-full h-full" src=src /> }
}); });
tracing::trace!("view");
view! { <div class=class>{img}</div> } view! { <div class=class>{img}</div> }
} }
#[server] #[server(
input = Ron,
output = Ron,
custom = RonEncoded
)]
#[tracing::instrument(skip_all, err)] #[tracing::instrument(skip_all, err)]
async fn get_wall(wall_id: models::WallUid) -> Result<RonCodec<models::Wall>, ServerFnError> { async fn get_wall(wall_uid: models::WallUid) -> Result<RonEncoded<models::Wall>, ServerFnError> {
let db = expect_context::<Arc<redb::Database>>(); tracing::debug!("Enter");
#[derive(Debug, derive_more::Error, derive_more::Display)] #[derive(Debug, derive_more::Error, derive_more::Display)]
enum Error { enum Error {
@@ -151,23 +177,43 @@ async fn get_wall(wall_id: models::WallUid) -> Result<RonCodec<models::Wall>, Se
NotFound(#[error(not(source))] models::WallUid), NotFound(#[error(not(source))] models::WallUid),
} }
let db = expect_context::<Arc<redb::Database>>();
let wall = tokio::task::spawn_blocking(move || -> Result<models::Wall, ServerFnError> { let wall = tokio::task::spawn_blocking(move || -> Result<models::Wall, ServerFnError> {
let read_txn = db.begin_read()?; let read_txn = db.begin_read()?;
let walls_table = read_txn.open_table(crate::server::db::current::TABLE_WALLS)?; let walls_table = read_txn.open_table(crate::server::db::current::TABLE_WALLS)?;
let wall = walls_table.get(wall_id)?.ok_or(Error::NotFound(wall_id))?.value(); let wall = walls_table.get(wall_uid)?.ok_or(Error::NotFound(wall_uid))?.value();
Ok(wall) Ok(wall)
}) })
.await??; .await??;
Ok(RonCodec::new(wall)) tracing::debug!("ok");
Ok(RonEncoded::new(wall))
} }
#[server] #[server(
input = Ron,
output = Ron,
custom = RonEncoded
)]
#[tracing::instrument(skip_all, err)] #[tracing::instrument(skip_all, err)]
async fn get_random_problem() -> Result<RonCodec<Option<models::Problem>>, ServerFnError> { async fn get_problem(wall_uid: models::WallUid, problem_uid: models::ProblemUid) -> Result<RonEncoded<Option<models::Problem>>, ServerFnError> {
Ok(RonCodec::new(None)) tracing::debug!("Enter");
let db = expect_context::<Arc<redb::Database>>();
let problem = tokio::task::spawn_blocking(move || -> Result<Option<models::Problem>, ServerFnError> {
let read_txn = db.begin_read()?;
let table = read_txn.open_table(crate::server::db::current::TABLE_PROBLEMS)?;
let problem = table.get((wall_uid, problem_uid))?.map(|guard| guard.value());
Ok(problem)
})
.await??;
// use rand::seq::IteratorRandom; // use rand::seq::IteratorRandom;
@@ -184,5 +230,5 @@ async fn get_random_problem() -> Result<RonCodec<Option<models::Problem>>, Serve
// tracing::debug!("Returning randomized problem: {problem:?}"); // tracing::debug!("Returning randomized problem: {problem:?}");
// Ok(RonCodec::new(problem)) Ok(RonEncoded::new(problem))
} }