diff --git a/Cargo.lock b/Cargo.lock index 2bedf02..0085d92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,7 +9,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a" dependencies = [ "abnf-core", - "nom", + "nom 7.1.3", ] [[package]] @@ -18,7 +18,7 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" dependencies = [ - "nom", + "nom 7.1.3", ] [[package]] @@ -48,7 +48,7 @@ version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -87,6 +87,15 @@ dependencies = [ "libc", ] +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + [[package]] name = "anstream" version = "0.6.21" @@ -190,6 +199,17 @@ version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi 0.1.19", + "libc", + "winapi", +] + [[package]] name = "autocfg" version = "1.5.0" @@ -213,7 +233,7 @@ dependencies = [ "hyper-util", "itoa", "matchit", - "memchr", + "memchr 2.7.6", "mime", "percent-encoding", "pin-project-lite", @@ -255,7 +275,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6" dependencies = [ "addr2line", - "cfg-if", + "cfg-if 1.0.4", "libc", "miniz_oxide", "object", @@ -424,7 +444,7 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63044e1ae8e69f3b5a92c736ca6269b8d12fa7efe39bf34ddb06d102cf0e2cab" dependencies = [ - "memchr", + "memchr 2.7.6", "serde", ] @@ -458,7 +478,7 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" dependencies = [ - "memchr", + "memchr 2.7.6", "safemem", ] @@ -519,6 +539,12 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.4" @@ -592,6 +618,21 @@ dependencies = [ "unsigned-varint", ] +[[package]] +name = "clap" +version = "2.34.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a0610544180c38b88101fecf2dd634b174a62eef6946f84dfc6a7127512b381c" +dependencies = [ + "ansi_term", + "atty", + "bitflags 1.3.2", + "strsim 0.8.0", + "textwrap 0.11.0", + "unicode-width 0.1.14", + "vec_map", +] + [[package]] name = "clap" version = "4.5.51" @@ -611,7 +652,7 @@ dependencies = [ "anstream", "anstyle", "clap_lex", - "strsim", + "strsim 0.11.1", "unicase", "unicode-width 0.2.2", ] @@ -634,6 +675,15 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1d728cc89cf3aee9ff92b05e62b19ee65a02b5702cff7d5a377e32c6ae29d8d" +[[package]] +name = "cloudabi" +version = "0.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" +dependencies = [ + "bitflags 1.3.2", +] + [[package]] name = "colorchoice" version = "1.0.4" @@ -647,7 +697,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" dependencies = [ "bytes", - "memchr", + "memchr 2.7.6", ] [[package]] @@ -668,7 +718,7 @@ checksum = "ef8a506ec4b81c460798f572caead636d57d3d7e940f998160f52bd254bf2d23" dependencies = [ "compression-core", "flate2", - "memchr", + "memchr 2.7.6", ] [[package]] @@ -763,7 +813,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b49ba7ef1ad6107f8824dbe97de947cbaac53c44e7f9756a1fba0d37c1eec505" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -781,7 +831,7 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -852,7 +902,7 @@ version = "4.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "cpufeatures", "curve25519-dalek-derive", "digest", @@ -903,7 +953,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.11.1", "syn 2.0.108", ] @@ -917,7 +967,7 @@ dependencies = [ "ident_case", "proc-macro2", "quote", - "strsim", + "strsim 0.11.1", "syn 2.0.108", ] @@ -949,12 +999,12 @@ version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "crossbeam-utils", "hashbrown 0.14.5", - "lock_api", + "lock_api 0.4.14", "once_cell", - "parking_lot_core", + "parking_lot_core 0.9.12", ] [[package]] @@ -1293,7 +1343,7 @@ version = "0.8.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -1390,7 +1440,7 @@ version = "0.2.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc0505cd1b6fa6580283f6bdf70a73fcf4aba1184038c90902b92b3dd0df63ed" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "libc", "libredox", "windows-sys 0.60.2", @@ -1402,6 +1452,12 @@ version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52051878f80a721bb68ebfbc930e07b65ba72f2da88968ea5c06fd6ca3d3a127" +[[package]] +name = "fixedbitset" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" + [[package]] name = "flate2" version = "1.1.5" @@ -1586,7 +1642,7 @@ dependencies = [ "futures-macro", "futures-sink", "futures-task", - "memchr", + "memchr 2.7.6", "pin-project-lite", "pin-utils", "slab", @@ -1599,7 +1655,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "605183a538e3e2a9c1038635cc5c2d194e2ee8fd0d1b66b8349fad7dbacce5a2" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.4", "libc", "log", "rustversion", @@ -1633,7 +1689,7 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "js-sys", "libc", "wasi", @@ -1646,7 +1702,7 @@ version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "js-sys", "libc", "r-efi", @@ -1724,7 +1780,7 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "crunchy", "zerocopy", ] @@ -1780,6 +1836,15 @@ version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + [[package]] name = "hermit-abi" version = "0.5.2" @@ -1805,7 +1870,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92652067c9ce6f66ce53cc38d1169daa36e6e7eb7dd3b63b5103bd9d97117248" dependencies = [ "async-trait", - "cfg-if", + "cfg-if 1.0.4", "data-encoding", "enum-as-inner", "futures-channel", @@ -1828,13 +1893,13 @@ version = "0.24.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cbb117a1ca520e111743ab2f6688eddee69db4e0ea242545a604dce8a66fd22e" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "futures-util", "hickory-proto", "ipconfig", "lru-cache", "once_cell", - "parking_lot", + "parking_lot 0.12.5", "rand 0.8.5", "resolv-conf", "smallvec", @@ -2150,7 +2215,7 @@ dependencies = [ "crossbeam-deque", "globset", "log", - "memchr", + "memchr 2.7.6", "regex-automata", "same-file", "walkdir", @@ -2265,7 +2330,7 @@ version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dbc5ebe9c3a1a7a5127f920a418f7585e9e758e911d0466ed004f393b0e380b2" dependencies = [ - "memchr", + "memchr 2.7.6", "serde", ] @@ -2290,7 +2355,7 @@ checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" [[package]] name = "jacquard" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "bytes", "getrandom 0.2.16", @@ -2319,7 +2384,7 @@ dependencies = [ [[package]] name = "jacquard-api" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "bon", "bytes", @@ -2337,7 +2402,7 @@ dependencies = [ [[package]] name = "jacquard-axum" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "axum", "bytes", @@ -2359,7 +2424,7 @@ dependencies = [ [[package]] name = "jacquard-common" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "base64 0.22.1", "bon", @@ -2402,7 +2467,7 @@ dependencies = [ [[package]] name = "jacquard-derive" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "heck 0.5.0", "jacquard-lexicon", @@ -2414,7 +2479,7 @@ dependencies = [ [[package]] name = "jacquard-identity" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "bon", "bytes", @@ -2441,7 +2506,7 @@ dependencies = [ [[package]] name = "jacquard-lexicon" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "cid", "dashmap", @@ -2467,7 +2532,7 @@ dependencies = [ [[package]] name = "jacquard-oauth" version = "0.8.0" -source = "git+https://tangled.org/@nonbinary.computer/jacquard#ece153be8332f8f222163257b910ba03d50951c8" +source = "git+https://tangled.org/@nonbinary.computer/jacquard#10d719d2a2c459ab562b2be6fecdfe11f52b521c" dependencies = [ "base64 0.22.1", "bytes", @@ -2504,7 +2569,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" dependencies = [ "cesu8", - "cfg-if", + "cfg-if 1.0.4", "combine", "jni-sys", "log", @@ -2536,7 +2601,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "de791f8b277ef903d49b0c6f3f3b866569ae8cb1d0829825eea28374cc4c803c" dependencies = [ "base64ct", - "cfg-if", + "cfg-if 1.0.4", "digest", "ecdsa", "ed25519-dalek", @@ -2614,7 +2679,7 @@ version = "0.13.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6e3919bbaa2945715f0bb6d3934a173d1e9a59ac23767fbaaef277265a7411b" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "ecdsa", "elliptic-curve", "sha2", @@ -2627,7 +2692,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e03e2e96c5926fe761088d66c8c2aee3a4352a2573f4eaca50043ad130af9117" dependencies = [ "miette 5.10.0", - "nom", + "nom 7.1.3", "thiserror 1.0.69", ] @@ -2691,7 +2756,7 @@ checksum = "416f7e718bdb06000964960ffa43b4335ad4012ae8b99060261aa4a8088d5ccb" dependencies = [ "bitflags 2.10.0", "libc", - "redox_syscall", + "redox_syscall 0.5.18", ] [[package]] @@ -2722,6 +2787,15 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +[[package]] +name = "lock_api" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4da24a77a3d8a6d4862d95f72e6fdb9c09a643ecdb402d754004a557f2bec75" +dependencies = [ + "scopeguard", +] + [[package]] name = "lock_api" version = "0.4.14" @@ -2743,7 +2817,7 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "generator", "scoped-tls", "tracing", @@ -2788,7 +2862,7 @@ dependencies = [ "bitflags 2.10.0", "getopts", "markdown-weaver-escape", - "memchr", + "memchr 2.7.6", "serde", "unicase", ] @@ -2856,7 +2930,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "digest", ] @@ -2869,6 +2943,15 @@ dependencies = [ "serde", ] +[[package]] +name = "memchr" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "148fab2e51b4f1cfc66da2a7c32981d1d3c083a803978268bb11fe4b86925e7a" +dependencies = [ + "libc", +] + [[package]] name = "memchr" version = "2.7.6" @@ -2895,7 +2978,7 @@ checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7" dependencies = [ "backtrace", "backtrace-ext", - "cfg-if", + "cfg-if 1.0.4", "miette-derive 7.6.0", "owo-colors", "supports-color", @@ -2903,7 +2986,7 @@ dependencies = [ "supports-unicode", "syntect", "terminal_size", - "textwrap", + "textwrap 0.16.2", "unicode-width 0.1.14", ] @@ -3026,7 +3109,7 @@ dependencies = [ "equivalent", "event-listener", "futures-util", - "parking_lot", + "parking_lot 0.12.5", "portable-atomic", "rustc_version", "smallvec", @@ -3125,13 +3208,22 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" +[[package]] +name = "nom" +version = "3.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05aec50c70fd288702bcd93284a8444607f3292dbdf2a30de5ea5dcdbe72287b" +dependencies = [ + "memchr 1.0.2", +] + [[package]] name = "nom" version = "7.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" dependencies = [ - "memchr", + "memchr 2.7.6", "minimal-lexical", ] @@ -3227,7 +3319,7 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" dependencies = [ - "hermit-abi", + "hermit-abi 0.5.2", "libc", ] @@ -3255,7 +3347,7 @@ version = "0.37.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -3299,7 +3391,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24ad14dd45412269e1a30f52ad8f0664f0f4f4a89ee8fe28c3b3527021ebb654" dependencies = [ "bitflags 2.10.0", - "cfg-if", + "cfg-if 1.0.4", "foreign-types", "libc", "once_cell", @@ -3411,14 +3503,38 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +[[package]] +name = "parking_lot" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3a704eb390aafdc107b0e392f56a82b668e3a71366993b5340f5833fd62505e" +dependencies = [ + "lock_api 0.3.4", + "parking_lot_core 0.7.3", +] + [[package]] name = "parking_lot" version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" dependencies = [ - "lock_api", - "parking_lot_core", + "lock_api 0.4.14", + "parking_lot_core 0.9.12", +] + +[[package]] +name = "parking_lot_core" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b93f386bb233083c799e6e642a9d73db98c24a5deeb95ffc85bf281255dffc98" +dependencies = [ + "cfg-if 0.1.10", + "cloudabi", + "libc", + "redox_syscall 0.1.57", + "smallvec", + "winapi", ] [[package]] @@ -3427,9 +3543,9 @@ version = "0.9.12" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "libc", - "redox_syscall", + "redox_syscall 0.5.18", "smallvec", "windows-link 0.2.1", ] @@ -3455,6 +3571,16 @@ version = "2.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +[[package]] +name = "petgraph" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "467d164a6de56270bd7c4d070df81d07beace25012d5103ced4e9ff08d6afdb7" +dependencies = [ + "fixedbitset", + "indexmap 1.9.3", +] + [[package]] name = "phf" version = "0.11.3" @@ -3602,7 +3728,7 @@ dependencies = [ "fallible-iterator", "hmac", "md-5", - "memchr", + "memchr 2.7.6", "rand 0.9.2", "sha2", "stringprep", @@ -3737,7 +3863,7 @@ version = "0.38.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42a232e7487fc2ef313d96dde7948e7a3c05101870d8985e4fd8d26aedd27b89" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -3881,6 +4007,12 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" +[[package]] +name = "redox_syscall" +version = "0.1.57" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41cc0f7e4d5d4544e8861606a285bb08d3e70712ccc7d2b84d7c0ccfaf4b05ce" + [[package]] name = "redox_syscall" version = "0.5.18" @@ -3928,7 +4060,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" dependencies = [ "aho-corasick", - "memchr", + "memchr 2.7.6", "regex-automata", "regex-syntax", ] @@ -3940,7 +4072,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" dependencies = [ "aho-corasick", - "memchr", + "memchr 2.7.6", "regex-syntax", ] @@ -4021,7 +4153,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" dependencies = [ "cc", - "cfg-if", + "cfg-if 1.0.4", "getrandom 0.2.16", "libc", "untrusted", @@ -4228,6 +4360,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" +[[package]] +name = "scoped_threadpool" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d51f5df5af43ab3f1360b429fa5e0152ac5ce8c0bd6485cae490332e96846a8" + [[package]] name = "scopeguard" version = "1.2.0" @@ -4400,7 +4538,7 @@ checksum = "402a6f66d8c709116cf22f558eab210f5a50187f702eb4d7e5ef38d9a7f1c79c" dependencies = [ "indexmap 2.12.0", "itoa", - "memchr", + "memchr 2.7.6", "ryu", "serde", "serde_core", @@ -4505,7 +4643,7 @@ version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "cpufeatures", "digest", ] @@ -4522,7 +4660,7 @@ version = "0.10.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "cpufeatures", "digest", ] @@ -4682,7 +4820,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ "new_debug_unreachable", - "parking_lot", + "parking_lot 0.12.5", "phf_shared 0.11.3", "precomputed-hash", "serde", @@ -4711,6 +4849,12 @@ dependencies = [ "unicode-properties", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" + [[package]] name = "strsim" version = "0.11.1" @@ -4829,6 +4973,15 @@ dependencies = [ "libc", ] +[[package]] +name = "tabwriter" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce91f2f0ec87dff7e6bcbbeb267439aa1188703003c6055193c821487400432" +dependencies = [ + "unicode-width 0.2.2", +] + [[package]] name = "tagptr" version = "0.2.0" @@ -4869,6 +5022,15 @@ dependencies = [ "windows-sys 0.60.2", ] +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +dependencies = [ + "unicode-width 0.1.14", +] + [[package]] name = "textwrap" version = "0.16.2" @@ -4925,7 +5087,7 @@ version = "1.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", ] [[package]] @@ -5016,7 +5178,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", + "parking_lot 0.12.5", "pin-project-lite", "signal-hook-registry", "socket2 0.6.1", @@ -5058,7 +5220,7 @@ dependencies = [ "futures-channel", "futures-util", "log", - "parking_lot", + "parking_lot 0.12.5", "percent-encoding", "phf 0.13.1", "pin-project-lite", @@ -5237,7 +5399,7 @@ dependencies = [ "cookie", "futures-util", "http", - "parking_lot", + "parking_lot 0.12.5", "pin-project-lite", "tower-layer", "tower-service", @@ -5303,7 +5465,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", - "parking_lot", + "parking_lot 0.12.5", "thiserror 1.0.69", "time", "tracing-subscriber", @@ -5383,6 +5545,24 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "tree_magic" +version = "0.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1d99367ce3e553a84738f73bd626ccca541ef90ae757fdcdc4cbe728e6cb629" +dependencies = [ + "clap 2.34.0", + "fnv", + "lazy_static", + "nom 3.2.1", + "num_cpus", + "parking_lot 0.10.2", + "petgraph", + "scoped_threadpool", + "tabwriter", + "walkdir", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -5415,7 +5595,7 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -5559,6 +5739,12 @@ version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" +[[package]] +name = "vec_map" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" + [[package]] name = "version_check" version = "0.9.5" @@ -5611,7 +5797,7 @@ version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da95793dfc411fbbd93f5be7715b0578ec61fe87cb1a42b12eb625caa5c5ea60" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "once_cell", "rustversion", "wasm-bindgen-macro", @@ -5624,7 +5810,7 @@ version = "0.4.55" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "551f88106c6d5e7ccc7cd9a16f312dd3b5d36ea8b4954304657d5dfba115d4a0" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "js-sys", "once_cell", "wasm-bindgen", @@ -5678,7 +5864,7 @@ dependencies = [ [[package]] name = "weaver-api" -version = "0.8.0" +version = "0.1.0" dependencies = [ "bytes", "jacquard-common", @@ -5698,7 +5884,7 @@ version = "0.1.0" dependencies = [ "axum", "chrono", - "clap", + "clap 4.5.51", "dashmap", "diesel", "diesel-async", @@ -5735,7 +5921,7 @@ dependencies = [ name = "weaver-cli" version = "0.1.0" dependencies = [ - "clap", + "clap 4.5.51", "dirs", "jacquard", "jacquard-api", @@ -5755,7 +5941,6 @@ dependencies = [ "hickory-resolver", "http", "jacquard", - "jacquard-api", "jose-jwk", "markdown-weaver", "markdown-weaver-escape", @@ -5779,6 +5964,8 @@ dependencies = [ "tower-service", "tracing", "trait-variant", + "tree_magic", + "weaver-api", "weaver-workspace-hack", ] @@ -5820,7 +6007,7 @@ name = "weaver-server" version = "0.1.0" dependencies = [ "axum", - "clap", + "clap 4.5.51", "jacquard", "jacquard-axum", "notify", @@ -5855,11 +6042,11 @@ dependencies = [ "jacquard-lexicon", "jacquard-oauth", "log", - "memchr", + "memchr 2.7.6", "miette 7.6.0", "minijinja", "minimal-lexical", - "nom", + "nom 7.1.3", "num-traits", "p384", "percent-encoding", @@ -5961,6 +6148,22 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72069c3113ab32ab29e5584db3c6ec55d416895e60715417b5b883a357c3e471" +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -5970,6 +6173,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows" version = "0.61.3" @@ -6432,7 +6641,7 @@ version = "0.7.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" dependencies = [ - "memchr", + "memchr 2.7.6", ] [[package]] @@ -6441,7 +6650,7 @@ version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "cfg-if", + "cfg-if 1.0.4", "windows-sys 0.48.0", ] diff --git a/Cargo.toml b/Cargo.toml index f867ec3..28c127f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -42,3 +42,4 @@ markdown-weaver-escape = { git = "https://github.com/rsform/markdown-weaver" } jacquard = { git = "https://tangled.org/@nonbinary.computer/jacquard", default-features = false, features = ["derive", "api_bluesky", "dns"] } jacquard-api = { git = "https://tangled.org/@nonbinary.computer/jacquard" } jacquard-axum = { git = "https://tangled.org/@nonbinary.computer/jacquard" } +tree_magic = { version = "0.2.3", features = ["cli"] } diff --git a/crates/weaver-api/Cargo.toml b/crates/weaver-api/Cargo.toml index faffbd6..5565d3b 100644 --- a/crates/weaver-api/Cargo.toml +++ b/crates/weaver-api/Cargo.toml @@ -2,7 +2,7 @@ name = "weaver-api" description = "Generated AT Protocol API bindings for Weaver" edition.workspace = true -version = "0.8.0" +version = "0.1.0" authors.workspace = true [dependencies] diff --git a/crates/weaver-api/lexicons/sh_weaver_edit_root.json b/crates/weaver-api/lexicons/sh_weaver_edit_root.json index 558fd34..9001075 100644 --- a/crates/weaver-api/lexicons/sh_weaver_edit_root.json +++ b/crates/weaver-api/lexicons/sh_weaver_edit_root.json @@ -9,16 +9,10 @@ "record": { "type": "object", "required": [ - "cid", - "uri", "doc", "snapshot" ], "properties": { - "cid": { - "type": "string", - "format": "cid" - }, "doc": { "type": "ref", "ref": "sh.weaver.edit.defs#docRef" @@ -29,10 +23,6 @@ "*/*" ], "maxSize": 30000000 - }, - "uri": { - "type": "string", - "format": "at-uri" } } } diff --git a/crates/weaver-api/lexicons/sh_weaver_embed_recordWithMedia.json b/crates/weaver-api/lexicons/sh_weaver_embed_recordWithMedia.json index ca8da5c..0c4e05f 100644 --- a/crates/weaver-api/lexicons/sh_weaver_embed_recordWithMedia.json +++ b/crates/weaver-api/lexicons/sh_weaver_embed_recordWithMedia.json @@ -6,7 +6,7 @@ "main": { "type": "object", "required": [ - "record", + "records", "media" ], "properties": { @@ -15,18 +15,12 @@ "refs": [ "sh.weaver.embed.images", "sh.weaver.embed.external", - "sh.weaver.embed.video", - "app.bsky.embed.images", - "app.bsky.embed.video", - "app.bsky.embed.external" + "sh.weaver.embed.video" ] }, - "record": { - "type": "union", - "refs": [ - "app.bsky.embed.record", - "sh.weaver.embed.records" - ] + "records": { + "type": "ref", + "ref": "sh.weaver.embed.records" } } }, @@ -42,18 +36,12 @@ "refs": [ "sh.weaver.embed.images#view", "sh.weaver.embed.external#view", - "sh.weaver.embed.video#view", - "app.bsky.embed.images#view", - "app.bsky.embed.video#view", - "app.bsky.embed.external#view" + "sh.weaver.embed.video#view" ] }, - "record": { - "type": "union", - "refs": [ - "sh.weaver.embed.records#view", - "app.bsky.embed.record#view" - ] + "records": { + "type": "ref", + "ref": "sh.weaver.embed.records#view" } } } diff --git a/crates/weaver-api/lexicons/sh_weaver_embed_records.json b/crates/weaver-api/lexicons/sh_weaver_embed_records.json index a2d0746..76df65f 100644 --- a/crates/weaver-api/lexicons/sh_weaver_embed_records.json +++ b/crates/weaver-api/lexicons/sh_weaver_embed_records.json @@ -48,11 +48,6 @@ "recordView": { "type": "union", "refs": [ - "app.bsky.embed.images#view", - "app.bsky.embed.video#view", - "app.bsky.embed.external#view", - "app.bsky.embed.record#view", - "app.bsky.embed.recordWithMedia#view", "sh.weaver.embed.records#view", "sh.weaver.embed.images#view", "sh.weaver.embed.recordWithMedia#view", diff --git a/crates/weaver-api/lexicons/sh_weaver_publish_blob.json b/crates/weaver-api/lexicons/sh_weaver_publish_blob.json index 18bad19..5ca781c 100644 --- a/crates/weaver-api/lexicons/sh_weaver_publish_blob.json +++ b/crates/weaver-api/lexicons/sh_weaver_publish_blob.json @@ -9,9 +9,15 @@ "record": { "type": "object", "required": [ - "upload" + "upload", + "path" ], "properties": { + "path": { + "type": "string", + "description": "relative path to the blob", + "minLength": 1 + }, "upload": { "type": "blob", "description": "Reference to the uploaded file", diff --git a/crates/weaver-api/src/sh_weaver/edit/root.rs b/crates/weaver-api/src/sh_weaver/edit/root.rs index e9dec52..b53c569 100644 --- a/crates/weaver-api/src/sh_weaver/edit/root.rs +++ b/crates/weaver-api/src/sh_weaver/edit/root.rs @@ -18,14 +18,10 @@ )] #[serde(rename_all = "camelCase")] pub struct Root<'a> { - #[serde(borrow)] - pub cid: jacquard_common::types::string::Cid<'a>, #[serde(borrow)] pub doc: crate::sh_weaver::edit::DocRef<'a>, #[serde(borrow)] pub snapshot: jacquard_common::types::blob::BlobRef<'a>, - #[serde(borrow)] - pub uri: jacquard_common::types::string::AtUri<'a>, } pub mod root_state { @@ -38,8 +34,6 @@ pub mod root_state { } /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { - type Cid; - type Uri; type Doc; type Snapshot; } @@ -47,35 +41,13 @@ pub mod root_state { pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { - type Cid = Unset; - type Uri = Unset; type Doc = Unset; type Snapshot = Unset; } - ///State transition - sets the `cid` field to Set - pub struct SetCid(PhantomData S>); - impl sealed::Sealed for SetCid {} - impl State for SetCid { - type Cid = Set; - type Uri = S::Uri; - type Doc = S::Doc; - type Snapshot = S::Snapshot; - } - ///State transition - sets the `uri` field to Set - pub struct SetUri(PhantomData S>); - impl sealed::Sealed for SetUri {} - impl State for SetUri { - type Cid = S::Cid; - type Uri = Set; - type Doc = S::Doc; - type Snapshot = S::Snapshot; - } ///State transition - sets the `doc` field to Set pub struct SetDoc(PhantomData S>); impl sealed::Sealed for SetDoc {} impl State for SetDoc { - type Cid = S::Cid; - type Uri = S::Uri; type Doc = Set; type Snapshot = S::Snapshot; } @@ -83,18 +55,12 @@ pub mod root_state { pub struct SetSnapshot(PhantomData S>); impl sealed::Sealed for SetSnapshot {} impl State for SetSnapshot { - type Cid = S::Cid; - type Uri = S::Uri; type Doc = S::Doc; type Snapshot = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { - ///Marker type for the `cid` field - pub struct cid(()); - ///Marker type for the `uri` field - pub struct uri(()); ///Marker type for the `doc` field pub struct doc(()); ///Marker type for the `snapshot` field @@ -106,10 +72,8 @@ pub mod root_state { pub struct RootBuilder<'a, S: root_state::State> { _phantom_state: ::core::marker::PhantomData S>, __unsafe_private_named: ( - ::core::option::Option>, ::core::option::Option>, ::core::option::Option>, - ::core::option::Option>, ), _phantom: ::core::marker::PhantomData<&'a ()>, } @@ -126,26 +90,7 @@ impl<'a> RootBuilder<'a, root_state::Empty> { pub fn new() -> Self { RootBuilder { _phantom_state: ::core::marker::PhantomData, - __unsafe_private_named: (None, None, None, None), - _phantom: ::core::marker::PhantomData, - } - } -} - -impl<'a, S> RootBuilder<'a, S> -where - S: root_state::State, - S::Cid: root_state::IsUnset, -{ - /// Set the `cid` field (required) - pub fn cid( - mut self, - value: impl Into>, - ) -> RootBuilder<'a, root_state::SetCid> { - self.__unsafe_private_named.0 = ::core::option::Option::Some(value.into()); - RootBuilder { - _phantom_state: ::core::marker::PhantomData, - __unsafe_private_named: self.__unsafe_private_named, + __unsafe_private_named: (None, None), _phantom: ::core::marker::PhantomData, } } @@ -161,7 +106,7 @@ where mut self, value: impl Into>, ) -> RootBuilder<'a, root_state::SetDoc> { - self.__unsafe_private_named.1 = ::core::option::Option::Some(value.into()); + self.__unsafe_private_named.0 = ::core::option::Option::Some(value.into()); RootBuilder { _phantom_state: ::core::marker::PhantomData, __unsafe_private_named: self.__unsafe_private_named, @@ -180,26 +125,7 @@ where mut self, value: impl Into>, ) -> RootBuilder<'a, root_state::SetSnapshot> { - self.__unsafe_private_named.2 = ::core::option::Option::Some(value.into()); - RootBuilder { - _phantom_state: ::core::marker::PhantomData, - __unsafe_private_named: self.__unsafe_private_named, - _phantom: ::core::marker::PhantomData, - } - } -} - -impl<'a, S> RootBuilder<'a, S> -where - S: root_state::State, - S::Uri: root_state::IsUnset, -{ - /// Set the `uri` field (required) - pub fn uri( - mut self, - value: impl Into>, - ) -> RootBuilder<'a, root_state::SetUri> { - self.__unsafe_private_named.3 = ::core::option::Option::Some(value.into()); + self.__unsafe_private_named.1 = ::core::option::Option::Some(value.into()); RootBuilder { _phantom_state: ::core::marker::PhantomData, __unsafe_private_named: self.__unsafe_private_named, @@ -211,18 +137,14 @@ where impl<'a, S> RootBuilder<'a, S> where S: root_state::State, - S::Cid: root_state::IsSet, - S::Uri: root_state::IsSet, S::Doc: root_state::IsSet, S::Snapshot: root_state::IsSet, { /// Build the final struct pub fn build(self) -> Root<'a> { Root { - cid: self.__unsafe_private_named.0.unwrap(), - doc: self.__unsafe_private_named.1.unwrap(), - snapshot: self.__unsafe_private_named.2.unwrap(), - uri: self.__unsafe_private_named.3.unwrap(), + doc: self.__unsafe_private_named.0.unwrap(), + snapshot: self.__unsafe_private_named.1.unwrap(), extra_data: Default::default(), } } @@ -235,10 +157,8 @@ where >, ) -> Root<'a> { Root { - cid: self.__unsafe_private_named.0.unwrap(), - doc: self.__unsafe_private_named.1.unwrap(), - snapshot: self.__unsafe_private_named.2.unwrap(), - uri: self.__unsafe_private_named.3.unwrap(), + doc: self.__unsafe_private_named.0.unwrap(), + snapshot: self.__unsafe_private_named.1.unwrap(), extra_data: Some(extra_data), } } @@ -345,8 +265,6 @@ fn lexicon_doc_sh_weaver_edit_root() -> ::jacquard_lexicon::lexicon::LexiconDoc< description: None, required: Some( vec![ - ::jacquard_common::smol_str::SmolStr::new_static("cid"), - ::jacquard_common::smol_str::SmolStr::new_static("uri"), ::jacquard_common::smol_str::SmolStr::new_static("doc"), ::jacquard_common::smol_str::SmolStr::new_static("snapshot") ], @@ -355,23 +273,6 @@ fn lexicon_doc_sh_weaver_edit_root() -> ::jacquard_lexicon::lexicon::LexiconDoc< properties: { #[allow(unused_mut)] let mut map = ::std::collections::BTreeMap::new(); - map.insert( - ::jacquard_common::smol_str::SmolStr::new_static("cid"), - ::jacquard_lexicon::lexicon::LexObjectProperty::String(::jacquard_lexicon::lexicon::LexString { - description: None, - format: Some( - ::jacquard_lexicon::lexicon::LexStringFormat::Cid, - ), - default: None, - min_length: None, - max_length: None, - min_graphemes: None, - max_graphemes: None, - r#enum: None, - r#const: None, - known_values: None, - }), - ); map.insert( ::jacquard_common::smol_str::SmolStr::new_static("doc"), ::jacquard_lexicon::lexicon::LexObjectProperty::Ref(::jacquard_lexicon::lexicon::LexRef { @@ -391,23 +292,6 @@ fn lexicon_doc_sh_weaver_edit_root() -> ::jacquard_lexicon::lexicon::LexiconDoc< max_size: None, }), ); - map.insert( - ::jacquard_common::smol_str::SmolStr::new_static("uri"), - ::jacquard_lexicon::lexicon::LexObjectProperty::String(::jacquard_lexicon::lexicon::LexString { - description: None, - format: Some( - ::jacquard_lexicon::lexicon::LexStringFormat::AtUri, - ), - default: None, - min_length: None, - max_length: None, - min_graphemes: None, - max_graphemes: None, - r#enum: None, - r#const: None, - known_values: None, - }), - ); map }, }), diff --git a/crates/weaver-api/src/sh_weaver/embed/record_with_media.rs b/crates/weaver-api/src/sh_weaver/embed/record_with_media.rs index 48e7e4d..a0d41b6 100644 --- a/crates/weaver-api/src/sh_weaver/embed/record_with_media.rs +++ b/crates/weaver-api/src/sh_weaver/embed/record_with_media.rs @@ -20,7 +20,7 @@ pub struct RecordWithMedia<'a> { #[serde(borrow)] pub media: RecordWithMediaMedia<'a>, #[serde(borrow)] - pub record: RecordWithMediaRecord<'a>, + pub records: crate::sh_weaver::embed::records::Records<'a>, } pub mod record_with_media_state { @@ -33,35 +33,35 @@ pub mod record_with_media_state { } /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { - type Record; + type Records; type Media; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { - type Record = Unset; + type Records = Unset; type Media = Unset; } - ///State transition - sets the `record` field to Set - pub struct SetRecord(PhantomData S>); - impl sealed::Sealed for SetRecord {} - impl State for SetRecord { - type Record = Set; + ///State transition - sets the `records` field to Set + pub struct SetRecords(PhantomData S>); + impl sealed::Sealed for SetRecords {} + impl State for SetRecords { + type Records = Set; type Media = S::Media; } ///State transition - sets the `media` field to Set pub struct SetMedia(PhantomData S>); impl sealed::Sealed for SetMedia {} impl State for SetMedia { - type Record = S::Record; + type Records = S::Records; type Media = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { - ///Marker type for the `record` field - pub struct record(()); + ///Marker type for the `records` field + pub struct records(()); ///Marker type for the `media` field pub struct media(()); } @@ -72,7 +72,7 @@ pub struct RecordWithMediaBuilder<'a, S: record_with_media_state::State> { _phantom_state: ::core::marker::PhantomData S>, __unsafe_private_named: ( ::core::option::Option>, - ::core::option::Option>, + ::core::option::Option>, ), _phantom: ::core::marker::PhantomData<&'a ()>, } @@ -117,13 +117,13 @@ where impl<'a, S> RecordWithMediaBuilder<'a, S> where S: record_with_media_state::State, - S::Record: record_with_media_state::IsUnset, + S::Records: record_with_media_state::IsUnset, { - /// Set the `record` field (required) - pub fn record( + /// Set the `records` field (required) + pub fn records( mut self, - value: impl Into>, - ) -> RecordWithMediaBuilder<'a, record_with_media_state::SetRecord> { + value: impl Into>, + ) -> RecordWithMediaBuilder<'a, record_with_media_state::SetRecords> { self.__unsafe_private_named.1 = ::core::option::Option::Some(value.into()); RecordWithMediaBuilder { _phantom_state: ::core::marker::PhantomData, @@ -136,14 +136,14 @@ where impl<'a, S> RecordWithMediaBuilder<'a, S> where S: record_with_media_state::State, - S::Record: record_with_media_state::IsSet, + S::Records: record_with_media_state::IsSet, S::Media: record_with_media_state::IsSet, { /// Build the final struct pub fn build(self) -> RecordWithMedia<'a> { RecordWithMedia { media: self.__unsafe_private_named.0.unwrap(), - record: self.__unsafe_private_named.1.unwrap(), + records: self.__unsafe_private_named.1.unwrap(), extra_data: Default::default(), } } @@ -157,7 +157,7 @@ where ) -> RecordWithMedia<'a> { RecordWithMedia { media: self.__unsafe_private_named.0.unwrap(), - record: self.__unsafe_private_named.1.unwrap(), + records: self.__unsafe_private_named.1.unwrap(), extra_data: Some(extra_data), } } @@ -182,31 +182,6 @@ pub enum RecordWithMediaMedia<'a> { External(Box>), #[serde(rename = "sh.weaver.embed.video")] Video(Box>), - #[serde(rename = "app.bsky.embed.images")] - BskyImages(Box>), - #[serde(rename = "app.bsky.embed.video")] - BskyVideo(Box>), - #[serde(rename = "app.bsky.embed.external")] - BskyExternal(Box>), -} - -#[jacquard_derive::open_union] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(tag = "$type")] -#[serde(bound(deserialize = "'de: 'a"))] -pub enum RecordWithMediaRecord<'a> { - #[serde(rename = "app.bsky.embed.record")] - Record(Box>), - #[serde(rename = "sh.weaver.embed.records")] - Records(Box>), } fn lexicon_doc_sh_weaver_embed_recordWithMedia() -> ::jacquard_lexicon::lexicon::LexiconDoc< @@ -225,7 +200,7 @@ fn lexicon_doc_sh_weaver_embed_recordWithMedia() -> ::jacquard_lexicon::lexicon: description: None, required: Some( vec![ - ::jacquard_common::smol_str::SmolStr::new_static("record"), + ::jacquard_common::smol_str::SmolStr::new_static("records"), ::jacquard_common::smol_str::SmolStr::new_static("media") ], ), @@ -240,23 +215,18 @@ fn lexicon_doc_sh_weaver_embed_recordWithMedia() -> ::jacquard_lexicon::lexicon: refs: vec![ ::jacquard_common::CowStr::new_static("sh.weaver.embed.images"), ::jacquard_common::CowStr::new_static("sh.weaver.embed.external"), - ::jacquard_common::CowStr::new_static("sh.weaver.embed.video"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.images"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.video"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.external") + ::jacquard_common::CowStr::new_static("sh.weaver.embed.video") ], closed: None, }), ); map.insert( - ::jacquard_common::smol_str::SmolStr::new_static("record"), - ::jacquard_lexicon::lexicon::LexObjectProperty::Union(::jacquard_lexicon::lexicon::LexRefUnion { + ::jacquard_common::smol_str::SmolStr::new_static("records"), + ::jacquard_lexicon::lexicon::LexObjectProperty::Ref(::jacquard_lexicon::lexicon::LexRef { description: None, - refs: vec![ - ::jacquard_common::CowStr::new_static("app.bsky.embed.record"), - ::jacquard_common::CowStr::new_static("sh.weaver.embed.records") - ], - closed: None, + r#ref: ::jacquard_common::CowStr::new_static( + "sh.weaver.embed.records", + ), }), ); map @@ -284,23 +254,18 @@ fn lexicon_doc_sh_weaver_embed_recordWithMedia() -> ::jacquard_lexicon::lexicon: refs: vec![ ::jacquard_common::CowStr::new_static("sh.weaver.embed.images#view"), ::jacquard_common::CowStr::new_static("sh.weaver.embed.external#view"), - ::jacquard_common::CowStr::new_static("sh.weaver.embed.video#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.images#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.video#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.external#view") + ::jacquard_common::CowStr::new_static("sh.weaver.embed.video#view") ], closed: None, }), ); map.insert( - ::jacquard_common::smol_str::SmolStr::new_static("record"), - ::jacquard_lexicon::lexicon::LexObjectProperty::Union(::jacquard_lexicon::lexicon::LexRefUnion { + ::jacquard_common::smol_str::SmolStr::new_static("records"), + ::jacquard_lexicon::lexicon::LexObjectProperty::Ref(::jacquard_lexicon::lexicon::LexRef { description: None, - refs: vec![ - ::jacquard_common::CowStr::new_static("sh.weaver.embed.records#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.record#view") - ], - closed: None, + r#ref: ::jacquard_common::CowStr::new_static( + "sh.weaver.embed.records#view", + ), }), ); map @@ -343,8 +308,9 @@ impl<'a> ::jacquard_lexicon::schema::LexiconSchema for RecordWithMedia<'a> { pub struct View<'a> { #[serde(borrow)] pub media: ViewMedia<'a>, + #[serde(skip_serializing_if = "std::option::Option::is_none")] #[serde(borrow)] - pub record: ViewRecord<'a>, + pub records: Option>, } pub mod view_state { @@ -396,7 +362,7 @@ pub struct ViewBuilder<'a, S: view_state::State> { _phantom_state: ::core::marker::PhantomData S>, __unsafe_private_named: ( ::core::option::Option>, - ::core::option::Option>, + ::core::option::Option>, ), _phantom: ::core::marker::PhantomData<&'a ()>, } @@ -438,22 +404,22 @@ where } } -impl<'a, S> ViewBuilder<'a, S> -where - S: view_state::State, - S::Record: view_state::IsUnset, -{ - /// Set the `record` field (required) - pub fn record( +impl<'a, S: view_state::State> ViewBuilder<'a, S> { + /// Set the `records` field (optional) + pub fn records( mut self, - value: impl Into>, - ) -> ViewBuilder<'a, view_state::SetRecord> { - self.__unsafe_private_named.1 = ::core::option::Option::Some(value.into()); - ViewBuilder { - _phantom_state: ::core::marker::PhantomData, - __unsafe_private_named: self.__unsafe_private_named, - _phantom: ::core::marker::PhantomData, - } + value: impl Into>>, + ) -> Self { + self.__unsafe_private_named.1 = value.into(); + self + } + /// Set the `records` field to an Option value (optional) + pub fn maybe_records( + mut self, + value: Option>, + ) -> Self { + self.__unsafe_private_named.1 = value; + self } } @@ -467,7 +433,7 @@ where pub fn build(self) -> View<'a> { View { media: self.__unsafe_private_named.0.unwrap(), - record: self.__unsafe_private_named.1.unwrap(), + records: self.__unsafe_private_named.1, extra_data: Default::default(), } } @@ -481,7 +447,7 @@ where ) -> View<'a> { View { media: self.__unsafe_private_named.0.unwrap(), - record: self.__unsafe_private_named.1.unwrap(), + records: self.__unsafe_private_named.1, extra_data: Some(extra_data), } } @@ -506,31 +472,6 @@ pub enum ViewMedia<'a> { ExternalView(Box>), #[serde(rename = "sh.weaver.embed.video#view")] VideoView(Box>), - #[serde(rename = "app.bsky.embed.images#view")] - BskyImagesView(Box>), - #[serde(rename = "app.bsky.embed.video#view")] - BskyVideoView(Box>), - #[serde(rename = "app.bsky.embed.external#view")] - BskyExternalView(Box>), -} - -#[jacquard_derive::open_union] -#[derive( - serde::Serialize, - serde::Deserialize, - Debug, - Clone, - PartialEq, - Eq, - jacquard_derive::IntoStatic -)] -#[serde(tag = "$type")] -#[serde(bound(deserialize = "'de: 'a"))] -pub enum ViewRecord<'a> { - #[serde(rename = "sh.weaver.embed.records#view")] - RecordsView(Box>), - #[serde(rename = "app.bsky.embed.record#view")] - RecordView(Box>), } impl<'a> ::jacquard_lexicon::schema::LexiconSchema for View<'a> { diff --git a/crates/weaver-api/src/sh_weaver/embed/records.rs b/crates/weaver-api/src/sh_weaver/embed/records.rs index d94e722..013a4e9 100644 --- a/crates/weaver-api/src/sh_weaver/embed/records.rs +++ b/crates/weaver-api/src/sh_weaver/embed/records.rs @@ -237,11 +237,6 @@ fn lexicon_doc_sh_weaver_embed_records() -> ::jacquard_lexicon::lexicon::Lexicon ::jacquard_lexicon::lexicon::LexObjectProperty::Union(::jacquard_lexicon::lexicon::LexRefUnion { description: None, refs: vec![ - ::jacquard_common::CowStr::new_static("app.bsky.embed.images#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.video#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.external#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.record#view"), - ::jacquard_common::CowStr::new_static("app.bsky.embed.recordWithMedia#view"), ::jacquard_common::CowStr::new_static("sh.weaver.embed.records#view"), ::jacquard_common::CowStr::new_static("sh.weaver.embed.images#view"), ::jacquard_common::CowStr::new_static("sh.weaver.embed.recordWithMedia#view"), @@ -957,16 +952,6 @@ where #[serde(tag = "$type")] #[serde(bound(deserialize = "'de: 'a"))] pub enum RecordEmbedViewRecordView<'a> { - #[serde(rename = "app.bsky.embed.images#view")] - BskyImagesView(Box>), - #[serde(rename = "app.bsky.embed.video#view")] - BskyVideoView(Box>), - #[serde(rename = "app.bsky.embed.external#view")] - ExternalView(Box>), - #[serde(rename = "app.bsky.embed.record#view")] - RecordView(Box>), - #[serde(rename = "app.bsky.embed.recordWithMedia#view")] - BskyRecordWithMediaView(Box>), #[serde(rename = "sh.weaver.embed.records#view")] View(Box>), #[serde(rename = "sh.weaver.embed.images#view")] diff --git a/crates/weaver-api/src/sh_weaver/publish/blob.rs b/crates/weaver-api/src/sh_weaver/publish/blob.rs index 4993bf1..c532043 100644 --- a/crates/weaver-api/src/sh_weaver/publish/blob.rs +++ b/crates/weaver-api/src/sh_weaver/publish/blob.rs @@ -18,6 +18,9 @@ )] #[serde(rename_all = "camelCase")] pub struct Blob<'a> { + /// relative path to the blob + #[serde(borrow)] + pub path: jacquard_common::CowStr<'a>, /// Reference to the uploaded file #[serde(borrow)] pub upload: jacquard_common::types::blob::BlobRef<'a>, @@ -34,24 +37,36 @@ pub mod blob_state { /// State trait tracking which required fields have been set pub trait State: sealed::Sealed { type Upload; + type Path; } /// Empty state - all required fields are unset pub struct Empty(()); impl sealed::Sealed for Empty {} impl State for Empty { type Upload = Unset; + type Path = Unset; } ///State transition - sets the `upload` field to Set pub struct SetUpload(PhantomData S>); impl sealed::Sealed for SetUpload {} impl State for SetUpload { type Upload = Set; + type Path = S::Path; + } + ///State transition - sets the `path` field to Set + pub struct SetPath(PhantomData S>); + impl sealed::Sealed for SetPath {} + impl State for SetPath { + type Upload = S::Upload; + type Path = Set; } /// Marker types for field names #[allow(non_camel_case_types)] pub mod members { ///Marker type for the `upload` field pub struct upload(()); + ///Marker type for the `path` field + pub struct path(()); } } @@ -59,6 +74,7 @@ pub mod blob_state { pub struct BlobBuilder<'a, S: blob_state::State> { _phantom_state: ::core::marker::PhantomData S>, __unsafe_private_named: ( + ::core::option::Option>, ::core::option::Option>, ), _phantom: ::core::marker::PhantomData<&'a ()>, @@ -76,7 +92,26 @@ impl<'a> BlobBuilder<'a, blob_state::Empty> { pub fn new() -> Self { BlobBuilder { _phantom_state: ::core::marker::PhantomData, - __unsafe_private_named: (None,), + __unsafe_private_named: (None, None), + _phantom: ::core::marker::PhantomData, + } + } +} + +impl<'a, S> BlobBuilder<'a, S> +where + S: blob_state::State, + S::Path: blob_state::IsUnset, +{ + /// Set the `path` field (required) + pub fn path( + mut self, + value: impl Into>, + ) -> BlobBuilder<'a, blob_state::SetPath> { + self.__unsafe_private_named.0 = ::core::option::Option::Some(value.into()); + BlobBuilder { + _phantom_state: ::core::marker::PhantomData, + __unsafe_private_named: self.__unsafe_private_named, _phantom: ::core::marker::PhantomData, } } @@ -92,7 +127,7 @@ where mut self, value: impl Into>, ) -> BlobBuilder<'a, blob_state::SetUpload> { - self.__unsafe_private_named.0 = ::core::option::Option::Some(value.into()); + self.__unsafe_private_named.1 = ::core::option::Option::Some(value.into()); BlobBuilder { _phantom_state: ::core::marker::PhantomData, __unsafe_private_named: self.__unsafe_private_named, @@ -105,11 +140,13 @@ impl<'a, S> BlobBuilder<'a, S> where S: blob_state::State, S::Upload: blob_state::IsSet, + S::Path: blob_state::IsSet, { /// Build the final struct pub fn build(self) -> Blob<'a> { Blob { - upload: self.__unsafe_private_named.0.unwrap(), + path: self.__unsafe_private_named.0.unwrap(), + upload: self.__unsafe_private_named.1.unwrap(), extra_data: Default::default(), } } @@ -122,7 +159,8 @@ where >, ) -> Blob<'a> { Blob { - upload: self.__unsafe_private_named.0.unwrap(), + path: self.__unsafe_private_named.0.unwrap(), + upload: self.__unsafe_private_named.1.unwrap(), extra_data: Some(extra_data), } } @@ -202,6 +240,19 @@ impl<'a> ::jacquard_lexicon::schema::LexiconSchema for Blob<'a> { fn validate( &self, ) -> ::std::result::Result<(), ::jacquard_lexicon::validation::ConstraintError> { + { + let value = &self.path; + #[allow(unused_comparisons)] + if ::len(value.as_ref()) < 1usize { + return Err(::jacquard_lexicon::validation::ConstraintError::MinLength { + path: ::jacquard_lexicon::validation::ValidationPath::from_field( + "path", + ), + min: 1usize, + actual: ::len(value.as_ref()), + }); + } + } Ok(()) } } @@ -229,13 +280,33 @@ fn lexicon_doc_sh_weaver_publish_blob() -> ::jacquard_lexicon::lexicon::LexiconD description: None, required: Some( vec![ - ::jacquard_common::smol_str::SmolStr::new_static("upload") + ::jacquard_common::smol_str::SmolStr::new_static("upload"), + ::jacquard_common::smol_str::SmolStr::new_static("path") ], ), nullable: None, properties: { #[allow(unused_mut)] let mut map = ::std::collections::BTreeMap::new(); + map.insert( + ::jacquard_common::smol_str::SmolStr::new_static("path"), + ::jacquard_lexicon::lexicon::LexObjectProperty::String(::jacquard_lexicon::lexicon::LexString { + description: Some( + ::jacquard_common::CowStr::new_static( + "relative path to the blob", + ), + ), + format: None, + default: None, + min_length: Some(1usize), + max_length: None, + min_graphemes: None, + max_graphemes: None, + r#enum: None, + r#const: None, + known_values: None, + }), + ); map.insert( ::jacquard_common::smol_str::SmolStr::new_static("upload"), ::jacquard_lexicon::lexicon::LexObjectProperty::Blob(::jacquard_lexicon::lexicon::LexBlob { diff --git a/crates/weaver-common/Cargo.toml b/crates/weaver-common/Cargo.toml index dd05b87..1cc35e5 100644 --- a/crates/weaver-common/Cargo.toml +++ b/crates/weaver-common/Cargo.toml @@ -13,13 +13,13 @@ native = ["tokio"] [dependencies] n0-future = { workspace = true } weaver-workspace-hack = { version = "0.1", path = "../weaver-workspace-hack" } +weaver-api = { version = "0.1", path = "../weaver-api" } markdown-weaver = { workspace = true } #libsqlite3-sys = { version = "0.30.1", features = ["bundled"] } http = "1.3.1" jacquard = { workspace = true } -jacquard-api = { workspace = true, features = ["sh_weaver"] } trait-variant = "0.1" serde = { workspace = true } @@ -58,7 +58,7 @@ multibase = "0.9.1" dirs = "6.0.0" regex = "1.11.1" markdown-weaver-escape = { workspace = true, features = ["std"] } - +tree_magic.workspace = true [dev-dependencies] diff --git a/crates/weaver-common/src/error.rs b/crates/weaver-common/src/error.rs index 2e3c29b..7375f0f 100644 --- a/crates/weaver-common/src/error.rs +++ b/crates/weaver-common/src/error.rs @@ -1,5 +1,6 @@ //! Error types for weaver - thin wrapper over jacquard errors +use jacquard::{types::string::AtStrError, xrpc::GenericXrpcError}; use miette::{Diagnostic, NamedSource, SourceOffset, SourceSpan}; use std::borrow::Cow; @@ -36,6 +37,14 @@ pub enum WeaverError { /// Task join error #[error(transparent)] Task(#[from] n0_future::task::JoinError), + + /// atproto string parsing error + #[error(transparent)] + AtprotoString(#[from] AtStrError), + + /// XRPC error + #[error(transparent)] + Xrpc(#[from] jacquard::xrpc::XrpcError), } /// Parse error with source code location information diff --git a/crates/weaver-common/src/lib.rs b/crates/weaver-common/src/lib.rs index 8497fa8..c277d30 100644 --- a/crates/weaver-common/src/lib.rs +++ b/crates/weaver-common/src/lib.rs @@ -4,16 +4,31 @@ pub mod error; // Re-export jacquard for convenience pub use jacquard; -use jacquard::CowStr; -pub use jacquard_api; +use jacquard::error::ClientError; +use jacquard::types::ident::AtIdentifier; +use jacquard::{CowStr, IntoStatic, xrpc}; pub use error::WeaverError; +use jacquard::types::tid::{Ticker, Tid}; -use jacquard::client::{Agent, AgentSession}; -use jacquard::types::blob::BlobRef; -use jacquard::types::string::{AtUri, Cid, Did}; -use jacquard_api::sh_weaver::notebook::{book, chapter, entry}; +use jacquard::bytes::Bytes; +use jacquard::client::{Agent, AgentError, AgentErrorKind, AgentSession, AgentSessionExt}; +use jacquard::prelude::*; +use jacquard::smol_str::SmolStr; +use jacquard::types::blob::{BlobRef, MimeType}; +use jacquard::types::string::{AtUri, Cid, Did, Handle, RecordKey}; +use jacquard::xrpc::Response; use std::path::Path; +use std::sync::LazyLock; +use tokio::sync::Mutex; +use weaver_api::com_atproto::repo::get_record::GetRecordResponse; +use weaver_api::com_atproto::repo::strong_ref::StrongRef; +use weaver_api::sh_weaver::notebook::{book, chapter, entry}; +use weaver_api::sh_weaver::publish::blob::Blob as PublishedBlob; + +use crate::error::ParseError; + +static W_TICKER: LazyLock> = LazyLock::new(|| Mutex::new(Ticker::new())); /// Extension trait providing weaver-specific multi-step operations on Agent /// @@ -26,8 +41,8 @@ use std::path::Path; /// - `agent.upload_blob()` - Upload a single blob /// /// This trait is for multi-step workflows that coordinate between multiple operations. -#[trait_variant::make(Send)] -pub trait WeaverExt { +//#[trait_variant::make(Send)] +pub trait WeaverExt: AgentSessionExt { /// Publish a notebook directory to the user's PDS /// /// Multi-step workflow: @@ -38,34 +53,117 @@ pub trait WeaverExt { /// 5. Create book record with entry refs /// /// Returns the AT-URI of the published book - async fn publish_notebook(&self, path: &Path) -> Result, WeaverError>; + fn publish_notebook( + &self, + path: &Path, + ) -> impl Future, WeaverError>>; - /// Upload assets from markdown content + /// Publish a blob to the user's PDS /// /// Multi-step workflow: - /// 1. Parse markdown for image/asset refs - /// 2. Upload each asset → BlobRef - /// 3. Return mapping of original path → BlobRef + /// 1. Upload blob to PDS + /// 2. Create blob record with CID /// - /// Used by renderer to transform local refs to atproto refs - async fn upload_assets( + /// Returns the AT-URI of the published blob + fn publish_blob<'a>( &self, - markdown: &str, - ) -> Result)>, WeaverError>; + blob: Bytes, + url_path: &'a str, + prev: Option, + ) -> impl Future, PublishedBlob<'a>), WeaverError>>; + + fn confirm_record_ref( + &self, + uri: &AtUri<'_>, + ) -> impl Future, WeaverError>>; } -impl WeaverExt for Agent { +impl WeaverExt for Agent { async fn publish_notebook(&self, _path: &Path) -> Result, WeaverError> { // TODO: Implementation todo!("publish_notebook not yet implemented") } - async fn upload_assets( + async fn publish_blob<'a>( &self, - _markdown: &str, - ) -> Result)>, WeaverError> { - // TODO: Implementation - todo!("upload_assets not yet implemented") + blob: Bytes, + url_path: &'a str, + prev: Option, + ) -> Result<(StrongRef<'a>, PublishedBlob<'a>), WeaverError> { + let mime_type = MimeType::new_owned(tree_magic::from_u8(blob.as_ref())); + + let blob = self.upload_blob(blob, mime_type).await?; + let publish_record = PublishedBlob::new() + .path(url_path) + .upload(BlobRef::Blob(blob)) + .build(); + let tid = W_TICKER.lock().await.next(prev); + let record = self + .create_record(publish_record.clone(), Some(RecordKey::any(tid.as_str())?)) + .await?; + let strong_ref = StrongRef::new().uri(record.uri).cid(record.cid).build(); + + Ok((strong_ref, publish_record)) + } + + async fn confirm_record_ref(&self, uri: &AtUri<'_>) -> Result, WeaverError> { + let rkey = uri.rkey().ok_or_else(|| { + AgentError::from( + ClientError::invalid_request("AtUri missing rkey") + .with_help("ensure the URI includes a record key after the collection"), + ) + })?; + + // Resolve authority (DID or handle) to get DID and PDS + use jacquard::types::ident::AtIdentifier; + let (repo_did, pds_url) = match uri.authority() { + AtIdentifier::Did(did) => { + let pds = self.pds_for_did(did).await.map_err(|e| { + AgentError::from( + ClientError::from(e) + .with_context("DID document resolution failed during record retrieval"), + ) + })?; + (did.clone(), pds) + } + AtIdentifier::Handle(handle) => self.pds_for_handle(handle).await.map_err(|e| { + AgentError::from( + ClientError::from(e) + .with_context("handle resolution failed during record retrieval"), + ) + })?, + }; + + // Make stateless XRPC call to that PDS (no auth required for public records) + use weaver_api::com_atproto::repo::get_record::GetRecord; + let request = GetRecord::new() + .repo(AtIdentifier::Did(repo_did)) + .collection( + uri.collection() + .expect("collection should exist if rkey does") + .clone(), + ) + .rkey(rkey.clone()) + .build(); + + let response: Response = { + let http_request = xrpc::build_http_request(&pds_url, &request, &self.opts().await) + .map_err(|e| AgentError::from(ClientError::transport(e)))?; + + let http_response = self + .send_http(http_request) + .await + .map_err(|e| AgentError::from(ClientError::transport(e)))?; + + xrpc::process_response(http_response) + } + .map_err(|e| AgentError::new(AgentErrorKind::Client, Some(e.into())))?; + let record = response.parse().map_err(|e| AgentError::xrpc(e))?; + let strong_ref = StrongRef::new() + .uri(record.uri) + .cid(record.cid.expect("when does this NOT have a CID?")) + .build(); + Ok(strong_ref.into_static()) } } @@ -77,7 +175,7 @@ pub struct PublishResult<'a> { /// CID of the book record pub cid: Cid<'a>, /// URIs of published entries - pub entries: Vec>, + pub entries: Vec>, } /// too many cows, so we have conversions @@ -173,3 +271,71 @@ pub fn aturi_to_http<'s>(aturi: &'s str, appview: &'s str) -> Option { + AtRecord(AtUri<'a>), + AtIdent(Did<'a>, Handle<'a>), + Web(jacquard::url::Url), + Path(markdown_weaver::CowStr<'a>), + Heading(markdown_weaver::CowStr<'a>), + Footnote(markdown_weaver::CowStr<'a>), +} + +impl<'a> LinkUri<'a> { + pub async fn resolve(dest_url: &'a str, agent: &Agent) -> LinkUri<'a> + where + A: AgentSession + IdentityResolver, + { + if dest_url.starts_with('@') { + if let Ok(handle) = Handle::new(dest_url) { + if let Ok(did) = agent.resolve_handle(&handle).await { + return Self::AtIdent(did, handle); + } + } + } else if dest_url.starts_with("did:") { + if let Ok(did) = Did::new(dest_url) { + if let Ok(doc) = agent.resolve_did_doc(&did).await { + if let Ok(doc) = doc.parse_validated() { + if let Some(handle) = doc.handles().first() { + return Self::AtIdent(did, handle.clone()); + } + } + } + } + } else if dest_url.starts_with('#') { + // local fragment + return Self::Heading(markdown_weaver::CowStr::Borrowed(dest_url)); + } else if dest_url.starts_with('^') { + // footnote + return Self::Footnote(markdown_weaver::CowStr::Borrowed(dest_url)); + } + if let Ok(url) = jacquard::url::Url::parse(dest_url) { + if let Some(uri) = jacquard::richtext::extract_at_uri_from_url( + url.as_str(), + jacquard::richtext::DEFAULT_EMBED_DOMAINS, + ) { + if let AtIdentifier::Handle(handle) = uri.authority() { + if let Ok(did) = agent.resolve_handle(handle).await { + let mut aturi = format!("at://{did}"); + if let Some(collection) = uri.collection() { + aturi.push_str(&format!("/{}", collection)); + if let Some(record) = uri.rkey() { + aturi.push_str(&format!("/{}", record.0)); + } + } + if let Ok(aturi) = AtUri::new_owned(aturi) { + return Self::AtRecord(aturi); + } + } + return Self::AtRecord(uri); + } else { + return Self::AtRecord(uri); + } + } else if url.scheme() == "http" || url.scheme() == "https" { + return Self::Web(url); + } + } + + LinkUri::Path(markdown_weaver::CowStr::Borrowed(dest_url)) + } +} diff --git a/crates/weaver-renderer/src/lib.rs b/crates/weaver-renderer/src/lib.rs index a4d18e4..9e1cd65 100644 --- a/crates/weaver-renderer/src/lib.rs +++ b/crates/weaver-renderer/src/lib.rs @@ -3,13 +3,10 @@ //! This crate works with the weaver-markdown crate to render and optionally upload markdown notebooks to your Atproto PDS. //! -use async_trait::async_trait; use markdown_weaver::CowStr; use markdown_weaver::Event; -use markdown_weaver::LinkType; use markdown_weaver::Tag; use n0_future::Stream; -use n0_future::StreamExt; use n0_future::pin; use n0_future::stream::once_future; use yaml_rust2::Yaml; diff --git a/crates/weaver-renderer/src/utils.rs b/crates/weaver-renderer/src/utils.rs index d3d8963..6df9d78 100644 --- a/crates/weaver-renderer/src/utils.rs +++ b/crates/weaver-renderer/src/utils.rs @@ -1,11 +1,8 @@ -use std::{fmt::Arguments, path::Path, sync::OnceLock}; +use std::{path::Path, sync::OnceLock}; use markdown_weaver::{CodeBlockKind, CowStr, Event, Tag}; -use markdown_weaver_escape::StrWrite; use miette::IntoDiagnostic; use n0_future::TryFutureExt; -use n0_future::io::AsyncWrite; -use n0_future::io::AsyncWriteExt; use regex::Regex; #[cfg(not(all(target_family = "wasm", target_os = "unknown")))] diff --git a/flake.nix b/flake.nix index 0d2769d..bc3b07d 100644 --- a/flake.nix +++ b/flake.nix @@ -109,7 +109,7 @@ # cargo won't be able to find the sources for all members. weaver-cli = craneLib.buildPackage (individualCrateArgs // { - pname = "${name}-cli"; + pname = "${name}"; cargoExtraArgs = "-p ${name}-cli"; src = fileSetForCrate ./crates/weaver-cli; }); @@ -217,34 +217,68 @@ }; }; - devShells.default = craneLib.devShell { - inherit name; - # Inherit inputs from checks. - checks = self.checks.${system}; - NIX_LD_LIBRARY_PATH = with pkgs; - lib.makeLibraryPath [ - stdenv.cc.cc - openssl - # ... + devShells.default = let + # dioxus-cli = pkgs.dioxus-cli.overrideAttrs (_: { + # postPatch = '' + # rm Cargo.lock + # cp ${./Dioxus.lock} Cargo.lock + # ''; + # cargoDeps = pkgs.rustPlatform.importCargoLock { + # lockFile = ./Dioxus.lock; + # }; + # }); + cargoLock = builtins.fromTOML (builtins.readFile ./Cargo.lock); + + wasmBindgen = + pkgs.lib.findFirst + (pkg: pkg.name == "wasm-bindgen") + (throw "Could not find wasm-bindgen package") + cargoLock.package; + + wasm-bindgen-cli = pkgs.buildWasmBindgenCli rec { + src = pkgs.fetchCrate { + pname = "wasm-bindgen-cli"; + version = wasmBindgen.version; + hash = "sha256-zLPFFgnqAWq5R2KkaTGAYqVQswfBEYm9x3OPjx8DJRY="; + }; + + cargoDeps = pkgs.rustPlatform.fetchCargoVendor { + inherit src; + inherit (src) pname version; + hash = "sha256-a2X9bzwnMWNt0fTf30qAiJ4noal/ET1jEtf5fBFj5OU="; + }; + }; + in + craneLib.devShell { + inherit name; + # Inherit inputs from checks. + checks = self.checks.${system}; + NIX_LD_LIBRARY_PATH = with pkgs; + lib.makeLibraryPath [ + stdenv.cc.cc + openssl + # ... + ]; + NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker"; + + LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:$NIX_LD_LIBRARY_PATH"; + DATABASE_URL = "postgres://postgres:@localhost/weaver_appview"; + + # Additional dev-shell environment variables can be set directly + # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; + + # Extra inputs can be added here; cargo and rustc are provided by default. + packages = with pkgs; [ + cargo-hakari + nixd + alejandra + diesel-cli + postgresql + cargo-insta + jq + dioxus-cli + wasm-bindgen-cli ]; - NIX_LD = lib.fileContents "${pkgs.stdenv.cc}/nix-support/dynamic-linker"; - - LD_LIBRARY_PATH = "$LD_LIBRARY_PATH:$NIX_LD_LIBRARY_PATH"; - DATABASE_URL = "postgres://postgres:@localhost/weaver_appview"; - - # Additional dev-shell environment variables can be set directly - # MY_CUSTOM_DEVELOPMENT_VAR = "something else"; - - # Extra inputs can be added here; cargo and rustc are provided by default. - packages = with pkgs; [ - cargo-hakari - nixd - alejandra - diesel-cli - postgresql - cargo-insta - jq - ]; - }; + }; }); } diff --git a/lexicons/sh/weaver/actor/defs.json b/lexicons/actor/defs.json similarity index 100% rename from lexicons/sh/weaver/actor/defs.json rename to lexicons/actor/defs.json diff --git a/lexicons/sh/weaver/actor/getProfile.json b/lexicons/actor/getProfile.json similarity index 100% rename from lexicons/sh/weaver/actor/getProfile.json rename to lexicons/actor/getProfile.json diff --git a/lexicons/sh/weaver/actor/profile.json b/lexicons/actor/profile.json similarity index 100% rename from lexicons/sh/weaver/actor/profile.json rename to lexicons/actor/profile.json diff --git a/lexicons/sh/weaver/edit/cursor.json b/lexicons/edit/cursor.json similarity index 100% rename from lexicons/sh/weaver/edit/cursor.json rename to lexicons/edit/cursor.json diff --git a/lexicons/sh/weaver/edit/defs.json b/lexicons/edit/defs.json similarity index 100% rename from lexicons/sh/weaver/edit/defs.json rename to lexicons/edit/defs.json diff --git a/lexicons/sh/weaver/edit/diff.json b/lexicons/edit/diff.json similarity index 100% rename from lexicons/sh/weaver/edit/diff.json rename to lexicons/edit/diff.json diff --git a/lexicons/sh/weaver/edit/root.json b/lexicons/edit/root.json similarity index 75% rename from lexicons/sh/weaver/edit/root.json rename to lexicons/edit/root.json index a14366b..08f77d0 100644 --- a/lexicons/sh/weaver/edit/root.json +++ b/lexicons/edit/root.json @@ -8,10 +8,8 @@ "key": "tid", "record": { "type": "object", - "required": ["cid", "uri", "doc", "snapshot"], + "required": ["doc", "snapshot"], "properties": { - "uri": { "type": "string", "format": "at-uri" }, - "cid": { "type": "string", "format": "cid" }, "snapshot": { "type": "blob", "accept": ["*/*"], diff --git a/lexicons/sh/weaver/embed/defs.json b/lexicons/embed/defs.json similarity index 100% rename from lexicons/sh/weaver/embed/defs.json rename to lexicons/embed/defs.json diff --git a/lexicons/sh/weaver/embed/external.json b/lexicons/embed/external.json similarity index 100% rename from lexicons/sh/weaver/embed/external.json rename to lexicons/embed/external.json diff --git a/lexicons/sh/weaver/embed/images.json b/lexicons/embed/images.json similarity index 100% rename from lexicons/sh/weaver/embed/images.json rename to lexicons/embed/images.json diff --git a/lexicons/embed/recordWithMedia.json b/lexicons/embed/recordWithMedia.json new file mode 100644 index 0000000..2c29135 --- /dev/null +++ b/lexicons/embed/recordWithMedia.json @@ -0,0 +1,35 @@ +{ + "lexicon": 1, + "id": "sh.weaver.embed.recordWithMedia", + "description": "A representation of a record embedded in a Weaver record (eg, a notebook entry), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card.", + "defs": { + "main": { + "type": "object", + "required": ["records", "media"], + "properties": { + "records": { + "type": "ref", + "ref": "sh.weaver.embed.records" + }, + "media": { + "type": "union", + "refs": ["sh.weaver.embed.images", "sh.weaver.embed.external", "sh.weaver.embed.video"] + } + } + }, + "view": { + "type": "object", + "required": ["record", "media"], + "properties": { + "records": { + "type": "ref", + "ref": "sh.weaver.embed.records#view" + }, + "media": { + "type": "union", + "refs": ["sh.weaver.embed.images#view", "sh.weaver.embed.external#view", "sh.weaver.embed.video#view"] + } + } + } + } +} diff --git a/lexicons/sh/weaver/embed/records.json b/lexicons/embed/records.json similarity index 94% rename from lexicons/sh/weaver/embed/records.json rename to lexicons/embed/records.json index 75a071b..0f5e343 100644 --- a/lexicons/sh/weaver/embed/records.json +++ b/lexicons/embed/records.json @@ -35,11 +35,6 @@ "recordView": { "type": "union", "refs": [ - "app.bsky.embed.images#view", - "app.bsky.embed.video#view", - "app.bsky.embed.external#view", - "app.bsky.embed.record#view", - "app.bsky.embed.recordWithMedia#view", "sh.weaver.embed.records#view", "sh.weaver.embed.images#view", "sh.weaver.embed.recordWithMedia#view", diff --git a/lexicons/sh/weaver/embed/video.json b/lexicons/embed/video.json similarity index 100% rename from lexicons/sh/weaver/embed/video.json rename to lexicons/embed/video.json diff --git a/lexicons/sh/weaver/notebook/authors.json b/lexicons/notebook/authors.json similarity index 100% rename from lexicons/sh/weaver/notebook/authors.json rename to lexicons/notebook/authors.json diff --git a/lexicons/sh/weaver/notebook/book.json b/lexicons/notebook/book.json similarity index 100% rename from lexicons/sh/weaver/notebook/book.json rename to lexicons/notebook/book.json diff --git a/lexicons/sh/weaver/notebook/chapter.json b/lexicons/notebook/chapter.json similarity index 100% rename from lexicons/sh/weaver/notebook/chapter.json rename to lexicons/notebook/chapter.json diff --git a/lexicons/sh/weaver/notebook/defs.json b/lexicons/notebook/defs.json similarity index 100% rename from lexicons/sh/weaver/notebook/defs.json rename to lexicons/notebook/defs.json diff --git a/lexicons/sh/weaver/notebook/entry.json b/lexicons/notebook/entry.json similarity index 100% rename from lexicons/sh/weaver/notebook/entry.json rename to lexicons/notebook/entry.json diff --git a/lexicons/sh/weaver/notebook/page.json b/lexicons/notebook/page.json similarity index 100% rename from lexicons/sh/weaver/notebook/page.json rename to lexicons/notebook/page.json diff --git a/lexicons/sh/weaver/publish/blob.json b/lexicons/publish/blob.json similarity index 72% rename from lexicons/sh/weaver/publish/blob.json rename to lexicons/publish/blob.json index 893f14a..60f1fc6 100644 --- a/lexicons/sh/weaver/publish/blob.json +++ b/lexicons/publish/blob.json @@ -8,8 +8,13 @@ "key": "tid", "record": { "type": "object", - "required": ["upload"], + "required": ["upload", "path"], "properties": { + "path": { + "type": "string", + "description": "relative path to the blob", + "minLength": 1 + }, "upload": { "type": "blob", "description": "Reference to the uploaded file", diff --git a/lexicons/sh/weaver/publish/defs.json b/lexicons/publish/defs.json similarity index 100% rename from lexicons/sh/weaver/publish/defs.json rename to lexicons/publish/defs.json diff --git a/lexicons/sh/weaver/embed/recordWithMedia.json b/lexicons/sh/weaver/embed/recordWithMedia.json deleted file mode 100644 index 63ffa57..0000000 --- a/lexicons/sh/weaver/embed/recordWithMedia.json +++ /dev/null @@ -1,49 +0,0 @@ -{ - "lexicon": 1, - "id": "sh.weaver.embed.recordWithMedia", - "description": "A representation of a record embedded in a Weaver record (eg, a notebook entry), alongside other compatible embeds. For example, a quote post and image, or a quote post and external URL card.", - "defs": { - "main": { - "type": "object", - "required": ["record", "media"], - "properties": { - "record": { - "type": "union", - "refs": ["app.bsky.embed.record", "sh.weaver.embed.records"] - }, - "media": { - "type": "union", - "refs": [ - "sh.weaver.embed.images", - "sh.weaver.embed.external", - "sh.weaver.embed.video", - "app.bsky.embed.images", - "app.bsky.embed.video", - "app.bsky.embed.external" - ] - } - } - }, - "view": { - "type": "object", - "required": ["record", "media"], - "properties": { - "record": { - "type": "union", - "refs": ["sh.weaver.embed.records#view", "app.bsky.embed.record#view"] - }, - "media": { - "type": "union", - "refs": [ - "sh.weaver.embed.images#view", - "sh.weaver.embed.external#view", - "sh.weaver.embed.video#view", - "app.bsky.embed.images#view", - "app.bsky.embed.video#view", - "app.bsky.embed.external#view" - ] - } - } - } - } -}