Removed the lazy submodules

Also some new lexicons related to loro CRDT format

+1060 -311
-5
.zed/settings.json
··· 12 12 } 13 13 } 14 14 } 15 - }, 16 - "rust-analyzer": { 17 - "binary": { 18 - "path_lookup": true 19 - } 20 15 } 21 16 }
+161 -194
Cargo.lock
··· 429 429 430 430 [[package]] 431 431 name = "bitflags" 432 - version = "2.9.0" 432 + version = "2.9.1" 433 433 source = "registry+https://github.com/rust-lang/crates.io-index" 434 - checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 434 + checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967" 435 435 436 436 [[package]] 437 437 name = "block-buffer" ··· 498 498 checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 499 499 500 500 [[package]] 501 - name = "camino" 502 - version = "1.1.9" 503 - source = "registry+https://github.com/rust-lang/crates.io-index" 504 - checksum = "8b96ec4966b5813e2c0507c1f86115c8c5abaadc3980879c3424042a02fd1ad3" 505 - 506 - [[package]] 507 501 name = "castaway" 508 502 version = "0.2.3" 509 503 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 523 517 524 518 [[package]] 525 519 name = "cc" 526 - version = "1.2.22" 520 + version = "1.2.23" 527 521 source = "registry+https://github.com/rust-lang/crates.io-index" 528 - checksum = "32db95edf998450acc7881c932f94cd9b05c87b4b2599e8bab064753da4acfd1" 522 + checksum = "5f4ac86a9e5bc1e2b3449ab9d7d3a6a405e3d1bb28d7b9be8614f55846ae3766" 529 523 dependencies = [ 530 524 "shlex", 531 525 ] ··· 968 962 source = "registry+https://github.com/rust-lang/crates.io-index" 969 963 checksum = "ff3e1edb1f37b4953dd5176916347289ed43d7119cc2e6c7c3f7849ff44ea506" 970 964 dependencies = [ 971 - "bitflags 2.9.0", 965 + "bitflags 2.9.1", 972 966 "byteorder", 973 967 "chrono", 974 968 "diesel_derives", ··· 1040 1034 ] 1041 1035 1042 1036 [[package]] 1037 + name = "dirs" 1038 + version = "6.0.0" 1039 + source = "registry+https://github.com/rust-lang/crates.io-index" 1040 + checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" 1041 + dependencies = [ 1042 + "dirs-sys", 1043 + ] 1044 + 1045 + [[package]] 1046 + name = "dirs-sys" 1047 + version = "0.5.0" 1048 + source = "registry+https://github.com/rust-lang/crates.io-index" 1049 + checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" 1050 + dependencies = [ 1051 + "libc", 1052 + "option-ext", 1053 + "redox_users", 1054 + "windows-sys 0.59.0", 1055 + ] 1056 + 1057 + [[package]] 1043 1058 name = "displaydoc" 1044 1059 version = "0.2.5" 1045 1060 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1165 1180 1166 1181 [[package]] 1167 1182 name = "errno" 1168 - version = "0.3.11" 1183 + version = "0.3.12" 1169 1184 source = "registry+https://github.com/rust-lang/crates.io-index" 1170 - checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" 1185 + checksum = "cea14ef9355e3beab063703aa9dab15afd25f0667c341310c1e5274bb1d0da18" 1171 1186 dependencies = [ 1172 1187 "libc", 1173 1188 "windows-sys 0.59.0", ··· 1217 1232 checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" 1218 1233 1219 1234 [[package]] 1220 - name = "fallible-iterator" 1221 - version = "0.3.0" 1222 - source = "registry+https://github.com/rust-lang/crates.io-index" 1223 - checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" 1224 - 1225 - [[package]] 1226 - name = "fallible-streaming-iterator" 1227 - version = "0.1.9" 1228 - source = "registry+https://github.com/rust-lang/crates.io-index" 1229 - checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" 1230 - 1231 - [[package]] 1232 1235 name = "fastrand" 1233 1236 version = "2.3.0" 1234 1237 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1415 1418 1416 1419 [[package]] 1417 1420 name = "generator" 1418 - version = "0.8.4" 1421 + version = "0.8.5" 1419 1422 source = "registry+https://github.com/rust-lang/crates.io-index" 1420 - checksum = "cc6bd114ceda131d3b1d665eba35788690ad37f5916457286b32ab6fd3c438dd" 1423 + checksum = "d18470a76cb7f8ff746cf1f7470914f900252ec36bbc40b569d74b1258446827" 1421 1424 dependencies = [ 1425 + "cc", 1422 1426 "cfg-if", 1423 1427 "libc", 1424 1428 "log", ··· 1467 1471 checksum = "26145e563e54f2cadc477553f1ec5ee650b00862f0a58bcd12cbdc5f0ea2d2f4" 1468 1472 dependencies = [ 1469 1473 "cfg-if", 1474 + "js-sys", 1470 1475 "libc", 1471 1476 "r-efi", 1472 1477 "wasi 0.14.2+wasi-0.2.4", 1478 + "wasm-bindgen", 1473 1479 ] 1474 1480 1475 1481 [[package]] ··· 1561 1567 ] 1562 1568 1563 1569 [[package]] 1564 - name = "hashlink" 1565 - version = "0.9.1" 1566 - source = "registry+https://github.com/rust-lang/crates.io-index" 1567 - checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 1568 - dependencies = [ 1569 - "hashbrown 0.14.5", 1570 - ] 1571 - 1572 - [[package]] 1573 1570 name = "heck" 1574 1571 version = "0.4.1" 1575 1572 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1938 1935 source = "registry+https://github.com/rust-lang/crates.io-index" 1939 1936 checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3" 1940 1937 dependencies = [ 1941 - "bitflags 2.9.0", 1938 + "bitflags 2.9.1", 1942 1939 "inotify-sys", 1943 1940 "libc", 1944 1941 ] ··· 2138 2135 ] 2139 2136 2140 2137 [[package]] 2141 - name = "lexical-parse-float" 2142 - version = "0.8.5" 2143 - source = "registry+https://github.com/rust-lang/crates.io-index" 2144 - checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" 2145 - dependencies = [ 2146 - "lexical-parse-integer", 2147 - "lexical-util", 2148 - "static_assertions", 2149 - ] 2150 - 2151 - [[package]] 2152 - name = "lexical-parse-integer" 2153 - version = "0.8.6" 2154 - source = "registry+https://github.com/rust-lang/crates.io-index" 2155 - checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" 2156 - dependencies = [ 2157 - "lexical-util", 2158 - "static_assertions", 2159 - ] 2160 - 2161 - [[package]] 2162 - name = "lexical-util" 2163 - version = "0.8.5" 2164 - source = "registry+https://github.com/rust-lang/crates.io-index" 2165 - checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" 2166 - dependencies = [ 2167 - "static_assertions", 2168 - ] 2169 - 2170 - [[package]] 2171 2138 name = "libc" 2172 2139 version = "0.2.172" 2173 2140 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2185 2152 source = "registry+https://github.com/rust-lang/crates.io-index" 2186 2153 checksum = "c0ff37bd590ca25063e35af745c343cb7a0271906fb7b37e4813e8f79f00268d" 2187 2154 dependencies = [ 2188 - "bitflags 2.9.0", 2155 + "bitflags 2.9.1", 2189 2156 "libc", 2190 2157 "redox_syscall", 2191 2158 ] ··· 2196 2163 source = "registry+https://github.com/rust-lang/crates.io-index" 2197 2164 checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" 2198 2165 dependencies = [ 2199 - "cc", 2200 2166 "pkg-config", 2201 2167 "vcpkg", 2202 2168 ] ··· 2267 2233 ] 2268 2234 2269 2235 [[package]] 2236 + name = "lru-slab" 2237 + version = "0.1.2" 2238 + source = "registry+https://github.com/rust-lang/crates.io-index" 2239 + checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" 2240 + 2241 + [[package]] 2270 2242 name = "markdown-weaver" 2271 2243 version = "0.13.0" 2272 - source = "git+https://github.com/rsform/markdown-weaver#34bc7ad2d7e6e9b9604ba61602b68589f271404e" 2244 + source = "git+https://github.com/rsform/markdown-weaver#593f968ec3c4515c23273715eaeb33801342439b" 2273 2245 dependencies = [ 2274 - "bitflags 2.9.0", 2246 + "bitflags 2.9.1", 2275 2247 "getopts", 2276 2248 "markdown-weaver-escape", 2277 2249 "memchr", 2278 - "serde", 2279 2250 "unicase", 2280 2251 ] 2281 2252 2282 2253 [[package]] 2283 2254 name = "markdown-weaver-escape" 2284 2255 version = "0.11.0" 2285 - source = "git+https://github.com/rsform/markdown-weaver#34bc7ad2d7e6e9b9604ba61602b68589f271404e" 2256 + source = "git+https://github.com/rsform/markdown-weaver#593f968ec3c4515c23273715eaeb33801342439b" 2286 2257 2287 2258 [[package]] 2288 2259 name = "matchers" ··· 2326 2297 2327 2298 [[package]] 2328 2299 name = "merde" 2329 - version = "10.0.6" 2300 + version = "10.0.7" 2330 2301 source = "registry+https://github.com/rust-lang/crates.io-index" 2331 - checksum = "5ec14139b169a3bb101da2dd8c0c2e47ddaf63000075662635c64c985bb5ae7b" 2302 + checksum = "edd8dc7668eb89ede52dc09d4b21a8c2f7c9cd47168ea1f82550f705615d9b99" 2332 2303 dependencies = [ 2333 2304 "merde_core", 2334 - "merde_json", 2335 - "merde_msgpack", 2336 2305 "merde_yaml", 2337 2306 ] 2338 2307 2339 2308 [[package]] 2340 2309 name = "merde_core" 2341 - version = "10.0.5" 2310 + version = "10.0.6" 2342 2311 source = "registry+https://github.com/rust-lang/crates.io-index" 2343 - checksum = "714d8f25279d095f8d23392476e2e82427e8689348e34f90ddc0712497e157de" 2312 + checksum = "e937026f22a5a3567bc402f1edf871ecab0e0222cd6f829ea58abae0185e759c" 2344 2313 dependencies = [ 2345 - "camino", 2346 2314 "compact_bytes", 2347 2315 "compact_str", 2348 - "ordered-float 4.6.0", 2349 - "rusqlite", 2316 + "ordered-float 5.0.0", 2350 2317 "serde", 2351 - "time", 2352 - ] 2353 - 2354 - [[package]] 2355 - name = "merde_json" 2356 - version = "10.0.5" 2357 - source = "registry+https://github.com/rust-lang/crates.io-index" 2358 - checksum = "d354c179fe95a0568c8ffb95c276f73556ecb95edca76f742505320e7545cea9" 2359 - dependencies = [ 2360 - "itoa", 2361 - "lexical-parse-float", 2362 - "merde_core", 2363 - "ryu", 2364 - ] 2365 - 2366 - [[package]] 2367 - name = "merde_msgpack" 2368 - version = "10.0.5" 2369 - source = "registry+https://github.com/rust-lang/crates.io-index" 2370 - checksum = "f2b710370fee77ca3cb8e6666a2586f26f3a653d7b2e338ede77a13c99108c5e" 2371 - dependencies = [ 2372 - "merde_core", 2373 - "rmp", 2374 2318 ] 2375 2319 2376 2320 [[package]] 2377 2321 name = "merde_yaml" 2378 - version = "10.0.5" 2322 + version = "10.0.6" 2379 2323 source = "registry+https://github.com/rust-lang/crates.io-index" 2380 - checksum = "cb581c31249876b3b385a2cc50fafc666adc9c316874819b7aac7266b3c26c17" 2324 + checksum = "7c36f61da594ecad0ed986ceeb5061eba47a36fcf839576ce525c7e4ff08f3fa" 2381 2325 dependencies = [ 2382 2326 "merde_core", 2383 2327 "yaml-rust2", ··· 2597 2541 source = "registry+https://github.com/rust-lang/crates.io-index" 2598 2542 checksum = "2fee8403b3d66ac7b26aee6e40a897d85dc5ce26f44da36b8b73e987cc52e943" 2599 2543 dependencies = [ 2600 - "bitflags 2.9.0", 2544 + "bitflags 2.9.1", 2601 2545 "filetime", 2602 2546 "fsevent-sys", 2603 2547 "inotify", ··· 2741 2685 source = "registry+https://github.com/rust-lang/crates.io-index" 2742 2686 checksum = "fedfea7d58a1f73118430a55da6a286e7b044961736ce96a16a17068ea25e5da" 2743 2687 dependencies = [ 2744 - "bitflags 2.9.0", 2688 + "bitflags 2.9.1", 2745 2689 "cfg-if", 2746 2690 "foreign-types", 2747 2691 "libc", ··· 2780 2724 ] 2781 2725 2782 2726 [[package]] 2727 + name = "option-ext" 2728 + version = "0.2.0" 2729 + source = "registry+https://github.com/rust-lang/crates.io-index" 2730 + checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" 2731 + 2732 + [[package]] 2783 2733 name = "ordered-float" 2784 2734 version = "2.10.1" 2785 2735 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2790 2740 2791 2741 [[package]] 2792 2742 name = "ordered-float" 2793 - version = "4.6.0" 2743 + version = "5.0.0" 2794 2744 source = "registry+https://github.com/rust-lang/crates.io-index" 2795 - checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951" 2745 + checksum = "e2c1f9f56e534ac6a9b8a4600bdf0f530fb393b5f393e7b4d03489c3cf0c3f01" 2796 2746 dependencies = [ 2797 2747 "num-traits", 2798 2748 ] ··· 2805 2755 2806 2756 [[package]] 2807 2757 name = "owo-colors" 2808 - version = "4.2.0" 2758 + version = "4.2.1" 2809 2759 source = "registry+https://github.com/rust-lang/crates.io-index" 2810 - checksum = "1036865bb9422d3300cf723f657c2851d0e9ab12567854b1f4eba3d77decf564" 2760 + checksum = "26995317201fa17f3656c36716aed4a7c81743a9634ac4c99c0eeda495db0cec" 2811 2761 2812 2762 [[package]] 2813 2763 name = "p256" ··· 2863 2813 ] 2864 2814 2865 2815 [[package]] 2866 - name = "paste" 2867 - version = "1.0.15" 2868 - source = "registry+https://github.com/rust-lang/crates.io-index" 2869 - checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 2870 - 2871 - [[package]] 2872 2816 name = "pem-rfc7468" 2873 2817 version = "0.7.0" 2874 2818 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2988 2932 "base64 0.22.1", 2989 2933 "byteorder", 2990 2934 "bytes", 2991 - "fallible-iterator 0.2.0", 2935 + "fallible-iterator", 2992 2936 "hmac", 2993 2937 "md-5", 2994 2938 "memchr", ··· 3004 2948 checksum = "613283563cd90e1dfc3518d548caee47e0e725455ed619881f5cf21f36de4b48" 3005 2949 dependencies = [ 3006 2950 "bytes", 3007 - "fallible-iterator 0.2.0", 2951 + "fallible-iterator", 3008 2952 "postgres-protocol", 3009 2953 ] 3010 2954 ··· 3087 3031 3088 3032 [[package]] 3089 3033 name = "quinn" 3090 - version = "0.11.6" 3034 + version = "0.11.8" 3091 3035 source = "registry+https://github.com/rust-lang/crates.io-index" 3092 - checksum = "62e96808277ec6f97351a2380e6c25114bc9e67037775464979f3037c92d05ef" 3036 + checksum = "626214629cda6781b6dc1d316ba307189c85ba657213ce642d9c77670f8202c8" 3093 3037 dependencies = [ 3094 3038 "bytes", 3039 + "cfg_aliases", 3095 3040 "pin-project-lite", 3096 3041 "quinn-proto", 3097 3042 "quinn-udp", ··· 3101 3046 "thiserror 2.0.12", 3102 3047 "tokio", 3103 3048 "tracing", 3049 + "web-time", 3104 3050 ] 3105 3051 3106 3052 [[package]] 3107 3053 name = "quinn-proto" 3108 - version = "0.11.9" 3054 + version = "0.11.12" 3109 3055 source = "registry+https://github.com/rust-lang/crates.io-index" 3110 - checksum = "a2fe5ef3495d7d2e377ff17b1a8ce2ee2ec2a18cde8b6ad6619d65d0701c135d" 3056 + checksum = "49df843a9161c85bb8aae55f101bc0bac8bcafd637a620d9122fd7e0b2f7422e" 3111 3057 dependencies = [ 3112 3058 "bytes", 3113 - "getrandom 0.2.16", 3114 - "rand 0.8.5", 3059 + "getrandom 0.3.3", 3060 + "lru-slab", 3061 + "rand 0.9.1", 3115 3062 "ring 0.17.14", 3116 3063 "rustc-hash", 3117 3064 "rustls 0.23.27", ··· 3125 3072 3126 3073 [[package]] 3127 3074 name = "quinn-udp" 3128 - version = "0.5.9" 3075 + version = "0.5.12" 3129 3076 source = "registry+https://github.com/rust-lang/crates.io-index" 3130 - checksum = "1c40286217b4ba3a71d644d752e6a0b71f13f1b6a2c5311acfcbe0c2418ed904" 3077 + checksum = "ee4e529991f949c5e25755532370b8af5d114acae52326361d68d47af64aa842" 3131 3078 dependencies = [ 3132 3079 "cfg_aliases", 3133 3080 "libc", ··· 3217 3164 source = "registry+https://github.com/rust-lang/crates.io-index" 3218 3165 checksum = "928fca9cf2aa042393a8325b9ead81d2f0df4cb12e1e24cef072922ccd99c5af" 3219 3166 dependencies = [ 3220 - "bitflags 2.9.0", 3167 + "bitflags 2.9.1", 3168 + ] 3169 + 3170 + [[package]] 3171 + name = "redox_users" 3172 + version = "0.5.0" 3173 + source = "registry+https://github.com/rust-lang/crates.io-index" 3174 + checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" 3175 + dependencies = [ 3176 + "getrandom 0.2.16", 3177 + "libredox", 3178 + "thiserror 2.0.12", 3221 3179 ] 3222 3180 3223 3181 [[package]] ··· 3381 3339 ] 3382 3340 3383 3341 [[package]] 3384 - name = "rmp" 3385 - version = "0.8.14" 3386 - source = "registry+https://github.com/rust-lang/crates.io-index" 3387 - checksum = "228ed7c16fa39782c3b3468e974aec2795e9089153cd08ee2e9aefb3613334c4" 3388 - dependencies = [ 3389 - "byteorder", 3390 - "num-traits", 3391 - "paste", 3392 - ] 3393 - 3394 - [[package]] 3395 3342 name = "rouille" 3396 3343 version = "3.6.2" 3397 3344 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3436 3383 ] 3437 3384 3438 3385 [[package]] 3439 - name = "rusqlite" 3440 - version = "0.32.1" 3441 - source = "registry+https://github.com/rust-lang/crates.io-index" 3442 - checksum = "7753b721174eb8ff87a9a0e799e2d7bc3749323e773db92e0984debb00019d6e" 3443 - dependencies = [ 3444 - "bitflags 2.9.0", 3445 - "fallible-iterator 0.3.0", 3446 - "fallible-streaming-iterator", 3447 - "hashlink 0.9.1", 3448 - "libsqlite3-sys", 3449 - "smallvec", 3450 - ] 3451 - 3452 - [[package]] 3453 3386 name = "rustc-demangle" 3454 3387 version = "0.1.24" 3455 3388 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3476 3409 source = "registry+https://github.com/rust-lang/crates.io-index" 3477 3410 checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" 3478 3411 dependencies = [ 3479 - "bitflags 2.9.0", 3412 + "bitflags 2.9.1", 3480 3413 "errno", 3481 3414 "libc", 3482 3415 "linux-raw-sys", ··· 3646 3579 source = "registry+https://github.com/rust-lang/crates.io-index" 3647 3580 checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" 3648 3581 dependencies = [ 3649 - "bitflags 2.9.0", 3582 + "bitflags 2.9.1", 3650 3583 "core-foundation", 3651 3584 "core-foundation-sys", 3652 3585 "libc", ··· 4061 3994 source = "registry+https://github.com/rust-lang/crates.io-index" 4062 3995 checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b" 4063 3996 dependencies = [ 4064 - "bitflags 2.9.0", 3997 + "bitflags 2.9.1", 4065 3998 "core-foundation", 4066 3999 "system-configuration-sys", 4067 4000 ] ··· 4295 4228 "async-trait", 4296 4229 "byteorder", 4297 4230 "bytes", 4298 - "fallible-iterator 0.2.0", 4231 + "fallible-iterator", 4299 4232 "futures-channel", 4300 4233 "futures-util", 4301 4234 "log", ··· 4417 4350 source = "registry+https://github.com/rust-lang/crates.io-index" 4418 4351 checksum = "0fdb0c213ca27a9f57ab69ddb290fd80d970922355b83ae380b395d3986b8a2e" 4419 4352 dependencies = [ 4420 - "bitflags 2.9.0", 4353 + "bitflags 2.9.1", 4421 4354 "bytes", 4422 4355 "futures-util", 4423 4356 "http", ··· 4858 4791 "atrium-oauth", 4859 4792 "atrium-xrpc-client", 4860 4793 "clap", 4794 + "dirs", 4861 4795 "esquema-codegen", 4862 4796 "hickory-resolver", 4863 4797 "miette", ··· 4878 4812 "atrium-identity", 4879 4813 "atrium-oauth", 4880 4814 "atrium-xrpc", 4815 + "dirs", 4881 4816 "esquema-codegen", 4882 4817 "hickory-resolver", 4883 4818 "http", 4884 4819 "jose-jwk", 4885 - "libsqlite3-sys", 4886 4820 "markdown-weaver", 4887 4821 "merde", 4888 4822 "miette", ··· 4912 4846 dependencies = [ 4913 4847 "atrium-api", 4914 4848 "compact_string", 4849 + "http", 4915 4850 "n0-future", 4851 + "url", 4916 4852 "weaver-common", 4917 4853 "weaver-workspace-hack", 4918 4854 ] ··· 4951 4887 "group", 4952 4888 "hashbrown 0.15.3", 4953 4889 "idna", 4954 - "libsqlite3-sys", 4955 4890 "log", 4956 4891 "memchr", 4957 4892 "miette", ··· 5081 5016 5082 5017 [[package]] 5083 5018 name = "windows" 5084 - version = "0.58.0" 5019 + version = "0.61.1" 5020 + source = "registry+https://github.com/rust-lang/crates.io-index" 5021 + checksum = "c5ee8f3d025738cb02bad7868bbb5f8a6327501e870bf51f1b455b0a2454a419" 5022 + dependencies = [ 5023 + "windows-collections", 5024 + "windows-core", 5025 + "windows-future", 5026 + "windows-link", 5027 + "windows-numerics", 5028 + ] 5029 + 5030 + [[package]] 5031 + name = "windows-collections" 5032 + version = "0.2.0" 5085 5033 source = "registry+https://github.com/rust-lang/crates.io-index" 5086 - checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6" 5034 + checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" 5087 5035 dependencies = [ 5088 5036 "windows-core", 5089 - "windows-targets 0.52.6", 5090 5037 ] 5091 5038 5092 5039 [[package]] 5093 5040 name = "windows-core" 5094 - version = "0.58.0" 5041 + version = "0.61.1" 5095 5042 source = "registry+https://github.com/rust-lang/crates.io-index" 5096 - checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99" 5043 + checksum = "46ec44dc15085cea82cf9c78f85a9114c463a369786585ad2882d1ff0b0acf40" 5097 5044 dependencies = [ 5098 5045 "windows-implement", 5099 5046 "windows-interface", 5100 - "windows-result 0.2.0", 5101 - "windows-strings 0.1.0", 5102 - "windows-targets 0.52.6", 5047 + "windows-link", 5048 + "windows-result", 5049 + "windows-strings 0.4.1", 5050 + ] 5051 + 5052 + [[package]] 5053 + name = "windows-future" 5054 + version = "0.2.1" 5055 + source = "registry+https://github.com/rust-lang/crates.io-index" 5056 + checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" 5057 + dependencies = [ 5058 + "windows-core", 5059 + "windows-link", 5060 + "windows-threading", 5103 5061 ] 5104 5062 5105 5063 [[package]] 5106 5064 name = "windows-implement" 5107 - version = "0.58.0" 5065 + version = "0.60.0" 5108 5066 source = "registry+https://github.com/rust-lang/crates.io-index" 5109 - checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b" 5067 + checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" 5110 5068 dependencies = [ 5111 5069 "proc-macro2", 5112 5070 "quote", ··· 5115 5073 5116 5074 [[package]] 5117 5075 name = "windows-interface" 5118 - version = "0.58.0" 5076 + version = "0.59.1" 5119 5077 source = "registry+https://github.com/rust-lang/crates.io-index" 5120 - checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515" 5078 + checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" 5121 5079 dependencies = [ 5122 5080 "proc-macro2", 5123 5081 "quote", ··· 5131 5089 checksum = "76840935b766e1b0a05c0066835fb9ec80071d4c09a16f6bd5f7e655e3c14c38" 5132 5090 5133 5091 [[package]] 5134 - name = "windows-registry" 5135 - version = "0.4.0" 5092 + name = "windows-numerics" 5093 + version = "0.2.0" 5136 5094 source = "registry+https://github.com/rust-lang/crates.io-index" 5137 - checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 5095 + checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" 5138 5096 dependencies = [ 5139 - "windows-result 0.3.2", 5140 - "windows-strings 0.3.1", 5141 - "windows-targets 0.53.0", 5097 + "windows-core", 5098 + "windows-link", 5142 5099 ] 5143 5100 5144 5101 [[package]] 5145 - name = "windows-result" 5146 - version = "0.2.0" 5102 + name = "windows-registry" 5103 + version = "0.4.0" 5147 5104 source = "registry+https://github.com/rust-lang/crates.io-index" 5148 - checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e" 5105 + checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" 5149 5106 dependencies = [ 5150 - "windows-targets 0.52.6", 5107 + "windows-result", 5108 + "windows-strings 0.3.1", 5109 + "windows-targets 0.53.0", 5151 5110 ] 5152 5111 5153 5112 [[package]] 5154 5113 name = "windows-result" 5155 - version = "0.3.2" 5114 + version = "0.3.3" 5156 5115 source = "registry+https://github.com/rust-lang/crates.io-index" 5157 - checksum = "c64fd11a4fd95df68efcfee5f44a294fe71b8bc6a91993e2791938abcc712252" 5116 + checksum = "4b895b5356fc36103d0f64dd1e94dfa7ac5633f1c9dd6e80fe9ec4adef69e09d" 5158 5117 dependencies = [ 5159 5118 "windows-link", 5160 5119 ] 5161 5120 5162 5121 [[package]] 5163 5122 name = "windows-strings" 5164 - version = "0.1.0" 5123 + version = "0.3.1" 5165 5124 source = "registry+https://github.com/rust-lang/crates.io-index" 5166 - checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" 5125 + checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 5167 5126 dependencies = [ 5168 - "windows-result 0.2.0", 5169 - "windows-targets 0.52.6", 5127 + "windows-link", 5170 5128 ] 5171 5129 5172 5130 [[package]] 5173 5131 name = "windows-strings" 5174 - version = "0.3.1" 5132 + version = "0.4.1" 5175 5133 source = "registry+https://github.com/rust-lang/crates.io-index" 5176 - checksum = "87fa48cc5d406560701792be122a10132491cff9d0aeb23583cc2dcafc847319" 5134 + checksum = "2a7ab927b2637c19b3dbe0965e75d8f2d30bdd697a1516191cad2ec4df8fb28a" 5177 5135 dependencies = [ 5178 5136 "windows-link", 5179 5137 ] ··· 5250 5208 "windows_x86_64_gnu 0.53.0", 5251 5209 "windows_x86_64_gnullvm 0.53.0", 5252 5210 "windows_x86_64_msvc 0.53.0", 5211 + ] 5212 + 5213 + [[package]] 5214 + name = "windows-threading" 5215 + version = "0.1.0" 5216 + source = "registry+https://github.com/rust-lang/crates.io-index" 5217 + checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" 5218 + dependencies = [ 5219 + "windows-link", 5253 5220 ] 5254 5221 5255 5222 [[package]] ··· 5415 5382 source = "registry+https://github.com/rust-lang/crates.io-index" 5416 5383 checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 5417 5384 dependencies = [ 5418 - "bitflags 2.9.0", 5385 + "bitflags 2.9.1", 5419 5386 ] 5420 5387 5421 5388 [[package]] ··· 5440 5407 checksum = "8902160c4e6f2fb145dbe9d6760a75e3c9522d8bf796ed7047c85919ac7115f8" 5441 5408 dependencies = [ 5442 5409 "arraydeque", 5443 - "hashlink 0.8.4", 5410 + "hashlink", 5444 5411 ] 5445 5412 5446 5413 [[package]]
+1 -1
Cargo.toml
··· 23 23 [workspace.dependencies] 24 24 25 25 serde = { version = "1.0", features = ["derive"] } 26 - merde = { version = "10.0.6", features = ["full"] } 26 + merde = { version = "10.0.6" } 27 27 28 28 minijinja = { version = "2.9.0", default-features = false } 29 29 minijinja-contrib = { version = "2.9.0", default-features = false }
+2 -1
crates/weaver-cli/Cargo.toml
··· 8 8 [dependencies] 9 9 clap = { version = "4.5", features = ["derive", "env", "cargo", "unicode"] } 10 10 n0-future = { workspace = true } 11 - weaver-common = { path = "../weaver-common" } 11 + weaver-common = { path = "../weaver-common", features = ["native"] } 12 12 weaver-workspace-hack = { version = "0.1", path = "../weaver-workspace-hack" } 13 13 miette = { workspace = true, features = ["fancy"] } 14 14 ··· 27 27 # temp for testing 28 28 tokio = { version = "1.45.0", features = ["full"] } 29 29 rouille = { version = "3.6.2", features = ["rustls"] } 30 + dirs = "6.0.0"
+114 -50
crates/weaver-cli/src/main.rs
··· 1 - use atrium_api::agent::Agent; 1 + use atrium_api::types::string::Did; 2 2 use atrium_oauth::AuthorizeOptions; 3 3 use atrium_oauth::CallbackParams; 4 4 use atrium_oauth::KnownScope; 5 5 use atrium_oauth::Scope; 6 + use miette::miette; 7 + use miette::{IntoDiagnostic, Result}; 6 8 use rouille::Server; 7 - use std::error; 9 + use std::path::Path; 10 + use std::path::PathBuf; 8 11 use tokio::sync::mpsc; 9 12 use weaver_common::agent::WeaverAgent; 10 13 14 + use clap::{Args, Parser, Subcommand}; 15 + 16 + #[derive(Parser)] 17 + #[command(version, about, long_about = None)] 18 + #[command(propagate_version = true)] 19 + struct Cli { 20 + #[command(subcommand)] 21 + command: Option<Commands>, 22 + } 23 + 24 + #[derive(Subcommand)] 25 + enum Commands { 26 + /// Authenticate with your atproto PDS, using your handle or the URL of the PDS. You can also set the HANDLE environment variable. 27 + Auth(AuthArgs), 28 + /// Test the native oauth client 29 + Run, 30 + } 31 + 32 + #[derive(Args)] 33 + struct AuthArgs { 34 + handle: Option<String>, 35 + } 36 + 11 37 #[tokio::main] 12 - async fn main() -> Result<(), Box<dyn error::Error>> { 13 - let (tx, mut rx) = mpsc::channel(5); 14 - let server = Server::new("0.0.0.0:4000", move |request| { 15 - create_callback_router(request, tx.clone()) 16 - }) 17 - .expect("Could not start server"); 18 - let (server_handle, server_stop) = server.stoppable(); 19 - let client = weaver_common::oauth::default_native_oauth_client()?; 20 - println!( 21 - "To authenticate with your PDS, visit:\r\n\t {}", 22 - client 23 - .authorize( 24 - std::env::var("HANDLE").unwrap_or(String::from("https://atproto.systems")), 25 - AuthorizeOptions { 26 - scopes: vec![ 27 - Scope::Known(KnownScope::Atproto), 28 - Scope::Known(KnownScope::TransitionGeneric) 29 - ], 30 - ..Default::default() 31 - } 32 - ) 33 - .await? 34 - ); 38 + async fn main() -> Result<()> { 39 + init_miette(); 40 + let args = Cli::parse(); 41 + let base_dir = weaver_common::filestore::config_dir(); 42 + tokio::fs::create_dir_all(&base_dir) 43 + .await 44 + .into_diagnostic()?; 45 + let client = weaver_common::oauth::test_native_oauth_client().into_diagnostic()?; 46 + let (session, server_handle) = if let Some(Commands::Auth(AuthArgs { handle })) = args.command { 47 + let handle = handle.unwrap_or(String::from("https://atproto.systems")); 48 + let (tx, mut rx) = mpsc::channel(5); 49 + let server = Server::new("0.0.0.0:4000", move |request| { 50 + create_callback_router(request, tx.clone()) 51 + }) 52 + .expect("Could not start server"); 53 + let (server_handle, server_stop) = server.stoppable(); 35 54 36 - let params = rx.recv().await.unwrap(); 37 - let (session, _) = client.callback(params).await?; 38 - server_stop 39 - .send(()) 40 - .expect("Failed to stop callback server"); 55 + println!( 56 + "To authenticate with your PDS, visit:\r\n\t {}", 57 + client 58 + .authorize( 59 + handle, 60 + AuthorizeOptions { 61 + scopes: vec![ 62 + Scope::Known(KnownScope::Atproto), 63 + Scope::Known(KnownScope::TransitionGeneric) 64 + ], 65 + ..Default::default() 66 + } 67 + ) 68 + .await 69 + .into_diagnostic()? 70 + ); 71 + 72 + let params = rx.recv().await.unwrap(); 73 + let (session, _) = client.callback(params).await.into_diagnostic()?; 74 + server_stop 75 + .send(()) 76 + .expect("Failed to stop callback server"); 77 + Ok::<_, weaver_common::Error>((session, Some(server_handle))) 78 + } else { 79 + let did = find_session_did(base_dir).await?; 80 + let session = client.restore(&did).await.into_diagnostic()?; 81 + Ok((session, None)) 82 + }?; 83 + 41 84 let agent = WeaverAgent::new(session); 42 85 let output = agent 43 86 .get_profile_pds(agent.did().await.unwrap().into()) 44 87 .await?; 45 88 println!("{output:?}"); 46 - 47 - // let agent = Agent::new(session); 48 - // let output = agent 49 - // .api 50 - // .app 51 - // .bsky 52 - // .feed 53 - // .get_timeline( 54 - // weaver_common::app::bsky::feed::get_timeline::ParametersData { 55 - // algorithm: None, 56 - // cursor: None, 57 - // limit: 3.try_into().ok(), 58 - // } 59 - // .into(), 60 - // ) 61 - // .await?; 62 - // for feed in &output.feed { 63 - // println!("{feed:?}"); 64 - // } 65 - server_handle.join().unwrap(); 89 + if let Some(server_handle) = server_handle { 90 + server_handle.join().unwrap(); 91 + } 66 92 Ok(()) 67 93 } 68 94 ··· 86 112 _ => rouille::Response::empty_404() 87 113 ) 88 114 } 115 + 116 + pub async fn find_session_did(path: impl AsRef<Path>) -> Result<Did> { 117 + let path = path.as_ref(); 118 + let mut dir = tokio::fs::read_dir(path).await.into_diagnostic()?; 119 + while let Some(entry) = dir.next_entry().await.into_diagnostic()? { 120 + let file_name = entry.file_name(); 121 + if let Some(file_name) = file_name.to_str() { 122 + if file_name.ends_with("_session.json") { 123 + let did_string = file_name 124 + .strip_suffix("_session.json") 125 + .expect("we JUST checked the suffix lol") 126 + .to_string(); 127 + let did = Did::new(did_string).expect("we should only be writing valid dids"); 128 + return Ok(did); 129 + } 130 + } 131 + } 132 + Err(miette!("couldn't find any existing sessions!")) 133 + } 134 + 135 + fn init_miette() { 136 + miette::set_hook(Box::new(|_| { 137 + Box::new( 138 + miette::MietteHandlerOpts::new() 139 + .terminal_links(true) 140 + //.rgb_colors(miette::RgbColors::) 141 + .with_cause_chain() 142 + .with_syntax_highlighting(miette::highlighters::SyntectHighlighter::default()) 143 + .color(true) 144 + .context_lines(5) 145 + .tab_width(2) 146 + .break_words(true) 147 + .build(), 148 + ) 149 + })) 150 + .expect("couldn't set the miette hook"); 151 + miette::set_panic_hook(); 152 + }
+4 -2
crates/weaver-common/Cargo.toml
··· 8 8 [features] 9 9 default = ["dev"] 10 10 dev = [] 11 + native = ["tokio"] 11 12 12 13 [dependencies] 13 14 n0-future = { workspace = true } 14 15 weaver-workspace-hack = { version = "0.1", path = "../weaver-workspace-hack" } 15 16 markdown-weaver = { workspace = true } 16 - libsqlite3-sys = { version = "0.30.1", features = ["bundled"] } 17 + #libsqlite3-sys = { version = "0.30.1", features = ["bundled"] } 17 18 18 19 http = "1.3.1" 19 20 ··· 53 54 #jose = { version = "0.0.2", features = ["crypto-rustcrypto"] } 54 55 jose-jwk = "0.1.2" 55 56 reqwest = "0.12.15" 56 - 57 + tokio = { version = "1.44", features = ["full"], optional = true } 57 58 58 59 tower-service = "0.3.3" 59 60 tower-layer = "0.3.3" 60 61 multibase = "0.9.1" 62 + dirs = "6.0.0" 61 63 62 64 63 65
+3
crates/weaver-common/src/error.rs
··· 75 75 #[error("HTTP client error: {0}")] 76 76 #[diagnostic_source] 77 77 HttpClient(Box<dyn std::error::Error + Send + Sync + 'static>), 78 + #[error("DNS TXT resolver error: {0}")] 79 + #[diagnostic_source] 80 + DnsTxtResolver(#[from] hickory_resolver::error::ResolveError), 78 81 } 79 82 80 83 /// Generic error type for XRPC errors.
+187
crates/weaver-common/src/filestore.rs
··· 1 + use crate::Error; 2 + use crate::error::WeaverErrorKind; 3 + use crate::error::{IoError, SerDeError}; 4 + use atrium_api::types::string::Did; 5 + use atrium_common::store::Store; 6 + use atrium_oauth::store::session::Session; 7 + use atrium_oauth::store::state::InternalStateData; 8 + use std::path::{Path, PathBuf}; 9 + 10 + pub struct SimpleJsonFileSessionStore<T = PathBuf> 11 + where 12 + T: AsRef<Path>, 13 + { 14 + path: T, 15 + } 16 + 17 + impl<T> SimpleJsonFileSessionStore<T> 18 + where 19 + T: AsRef<Path>, 20 + { 21 + pub fn new(path: T) -> Self { 22 + Self { path } 23 + } 24 + 25 + pub async fn get_session(&self, did: &Did) -> Result<Option<Session>, Error> { 26 + let path = self 27 + .path 28 + .as_ref() 29 + .join(format!("{}_session.json", did.as_str())); 30 + let file = tokio::fs::read_to_string(path) 31 + .await 32 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))])); 33 + let file = if let Err(e) = &file { 34 + println!("Failed to read session file: {e}"); 35 + return Ok(None); 36 + } else { 37 + file? 38 + }; 39 + 40 + let session = serde_json::from_str(&file) 41 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(SerDeError::from(e))]))?; 42 + Ok(Some(session)) 43 + } 44 + 45 + pub async fn set_session(&self, did: Did, session: Session) -> Result<(), Error> { 46 + let path = self 47 + .path 48 + .as_ref() 49 + .join(format!("{}_session.json", did.as_str())); 50 + let file = serde_json::to_string(&session) 51 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(SerDeError::from(e))]))?; 52 + 53 + tokio::fs::write(path, file) 54 + .await 55 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 56 + 57 + Ok(()) 58 + } 59 + 60 + pub async fn get_state(&self, key: &str) -> Result<Option<InternalStateData>, Error> { 61 + let path = self.path.as_ref().join(format!("{}_state.json", key)); 62 + let file = tokio::fs::read_to_string(path) 63 + .await 64 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))])); 65 + let file = if let Err(e) = &file { 66 + println!("Failed to read state file: {e}"); 67 + return Ok(None); 68 + } else { 69 + file? 70 + }; 71 + let state = serde_json::from_str(&file) 72 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(SerDeError::from(e))]))?; 73 + Ok(Some(state)) 74 + } 75 + 76 + pub async fn set_state(&self, key: String, state: InternalStateData) -> Result<(), Error> { 77 + let path = self.path.as_ref().join(format!("{}_state.json", key)); 78 + 79 + let file = serde_json::to_string(&state) 80 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(SerDeError::from(e))]))?; 81 + 82 + tokio::fs::write(path, file) 83 + .await 84 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 85 + 86 + Ok(()) 87 + } 88 + } 89 + 90 + impl Store<Did, Session> for SimpleJsonFileSessionStore<PathBuf> { 91 + type Error = crate::Error; 92 + 93 + async fn get(&self, key: &Did) -> Result<Option<Session>, Self::Error> { 94 + self.get_session(key).await 95 + } 96 + 97 + async fn set(&self, key: Did, value: Session) -> Result<(), Self::Error> { 98 + self.set_session(key, value).await 99 + } 100 + 101 + async fn del(&self, key: &Did) -> Result<(), Self::Error> { 102 + let path = self.path.join(format!("{}_session.json", key.as_str())); 103 + tokio::fs::remove_file(path) 104 + .await 105 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))])) 106 + } 107 + 108 + async fn clear(&self) -> Result<(), Self::Error> { 109 + let mut files = tokio::fs::read_dir(&self.path) 110 + .await 111 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 112 + while let Some(entry) = files 113 + .next_entry() 114 + .await 115 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))? 116 + { 117 + let file_name = entry.file_name(); 118 + if let Some(file_name) = file_name.to_str() { 119 + if file_name.ends_with("_session.json") { 120 + tokio::fs::remove_file(entry.path()) 121 + .await 122 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 123 + } 124 + } 125 + } 126 + Ok(()) 127 + } 128 + } 129 + 130 + impl Store<String, InternalStateData> for SimpleJsonFileSessionStore<PathBuf> { 131 + type Error = crate::Error; 132 + 133 + async fn get(&self, key: &String) -> Result<Option<InternalStateData>, Self::Error> { 134 + self.get_state(key.as_str()).await 135 + } 136 + 137 + async fn set(&self, key: String, value: InternalStateData) -> Result<(), Self::Error> { 138 + self.set_state(key, value).await 139 + } 140 + 141 + async fn del(&self, key: &String) -> Result<(), Self::Error> { 142 + let path = self.path.join(format!("{}_state.json", key.as_str())); 143 + tokio::fs::remove_file(path) 144 + .await 145 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))])) 146 + } 147 + 148 + async fn clear(&self) -> Result<(), Self::Error> { 149 + let mut files = tokio::fs::read_dir(&self.path) 150 + .await 151 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 152 + while let Some(entry) = files 153 + .next_entry() 154 + .await 155 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))? 156 + { 157 + let file_name = &entry.file_name(); 158 + if let Some(file_name) = file_name.to_str() { 159 + if file_name.ends_with("_state.json") { 160 + tokio::fs::remove_file(entry.path()) 161 + .await 162 + .map_err(|e| Error::new(vec![WeaverErrorKind::from(IoError::from(e))]))?; 163 + } 164 + } 165 + } 166 + Ok(()) 167 + } 168 + } 169 + 170 + impl atrium_oauth::store::session::SessionStore for SimpleJsonFileSessionStore<PathBuf> {} 171 + 172 + impl atrium_oauth::store::state::StateStore for SimpleJsonFileSessionStore<PathBuf> {} 173 + 174 + impl Default for SimpleJsonFileSessionStore<PathBuf> { 175 + fn default() -> Self { 176 + let path = dirs::config_dir() 177 + .unwrap_or_else(|| PathBuf::from("./")) 178 + .join("weaver/sessions"); 179 + Self { path } 180 + } 181 + } 182 + 183 + pub fn config_dir() -> PathBuf { 184 + dirs::config_dir() 185 + .unwrap_or_else(|| PathBuf::from("./")) 186 + .join("weaver/sessions") 187 + }
+9
crates/weaver-common/src/lexicons/app/bsky/unspecced/get_config.rs
··· 6 6 pub struct OutputData { 7 7 #[serde(skip_serializing_if = "core::option::Option::is_none")] 8 8 pub check_email_confirmed: core::option::Option<bool>, 9 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 10 + pub live_now: core::option::Option<Vec<LiveNowConfig>>, 9 11 } 10 12 pub type Output = atrium_api::types::Object<OutputData>; 11 13 #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] ··· 16 18 Ok(()) 17 19 } 18 20 } 21 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 22 + #[serde(rename_all = "camelCase")] 23 + pub struct LiveNowConfigData { 24 + pub did: atrium_api::types::string::Did, 25 + pub domains: Vec<String>, 26 + } 27 + pub type LiveNowConfig = atrium_api::types::Object<LiveNowConfigData>;
+36
crates/weaver-common/src/lexicons/record.rs
··· 65 65 LexiconsShWeaverActorProfile( 66 66 Box<crate::lexicons::sh::weaver::actor::profile::Record>, 67 67 ), 68 + #[serde(rename = "sh.weaver.edit.cursor")] 69 + LexiconsShWeaverEditCursor(Box<crate::lexicons::sh::weaver::edit::cursor::Record>), 70 + #[serde(rename = "sh.weaver.edit.diff")] 71 + LexiconsShWeaverEditDiff(Box<crate::lexicons::sh::weaver::edit::diff::Record>), 72 + #[serde(rename = "sh.weaver.edit.root")] 73 + LexiconsShWeaverEditRoot(Box<crate::lexicons::sh::weaver::edit::root::Record>), 68 74 #[serde(rename = "sh.weaver.notebook.authors")] 69 75 LexiconsShWeaverNotebookAuthors( 70 76 Box<crate::lexicons::sh::weaver::notebook::authors::Record>, ··· 302 308 record_data: crate::lexicons::sh::weaver::actor::profile::RecordData, 303 309 ) -> Self { 304 310 KnownRecord::LexiconsShWeaverActorProfile(Box::new(record_data.into())) 311 + } 312 + } 313 + impl From<crate::lexicons::sh::weaver::edit::cursor::Record> for KnownRecord { 314 + fn from(record: crate::lexicons::sh::weaver::edit::cursor::Record) -> Self { 315 + KnownRecord::LexiconsShWeaverEditCursor(Box::new(record)) 316 + } 317 + } 318 + impl From<crate::lexicons::sh::weaver::edit::cursor::RecordData> for KnownRecord { 319 + fn from(record_data: crate::lexicons::sh::weaver::edit::cursor::RecordData) -> Self { 320 + KnownRecord::LexiconsShWeaverEditCursor(Box::new(record_data.into())) 321 + } 322 + } 323 + impl From<crate::lexicons::sh::weaver::edit::diff::Record> for KnownRecord { 324 + fn from(record: crate::lexicons::sh::weaver::edit::diff::Record) -> Self { 325 + KnownRecord::LexiconsShWeaverEditDiff(Box::new(record)) 326 + } 327 + } 328 + impl From<crate::lexicons::sh::weaver::edit::diff::RecordData> for KnownRecord { 329 + fn from(record_data: crate::lexicons::sh::weaver::edit::diff::RecordData) -> Self { 330 + KnownRecord::LexiconsShWeaverEditDiff(Box::new(record_data.into())) 331 + } 332 + } 333 + impl From<crate::lexicons::sh::weaver::edit::root::Record> for KnownRecord { 334 + fn from(record: crate::lexicons::sh::weaver::edit::root::Record) -> Self { 335 + KnownRecord::LexiconsShWeaverEditRoot(Box::new(record)) 336 + } 337 + } 338 + impl From<crate::lexicons::sh::weaver::edit::root::RecordData> for KnownRecord { 339 + fn from(record_data: crate::lexicons::sh::weaver::edit::root::RecordData) -> Self { 340 + KnownRecord::LexiconsShWeaverEditRoot(Box::new(record_data.into())) 305 341 } 306 342 } 307 343 impl From<crate::lexicons::sh::weaver::notebook::authors::Record> for KnownRecord {
+1
crates/weaver-common/src/lexicons/sh/weaver.rs
··· 1 1 // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 2 //!Definitions for the `sh.weaver` namespace. 3 3 pub mod actor; 4 + pub mod edit; 4 5 pub mod embed; 5 6 pub mod notebook;
+24
crates/weaver-common/src/lexicons/sh/weaver/edit.rs
··· 1 + // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 + //!Definitions for the `sh.weaver.edit` namespace. 3 + pub mod cursor; 4 + pub mod defs; 5 + pub mod diff; 6 + pub mod root; 7 + #[derive(Debug)] 8 + pub struct Cursor; 9 + impl atrium_api::types::Collection for Cursor { 10 + const NSID: &'static str = "sh.weaver.edit.cursor"; 11 + type Record = cursor::Record; 12 + } 13 + #[derive(Debug)] 14 + pub struct Diff; 15 + impl atrium_api::types::Collection for Diff { 16 + const NSID: &'static str = "sh.weaver.edit.diff"; 17 + type Record = diff::Record; 18 + } 19 + #[derive(Debug)] 20 + pub struct Root; 21 + impl atrium_api::types::Collection for Root { 22 + const NSID: &'static str = "sh.weaver.edit.root"; 23 + type Record = root::Record; 24 + }
+61
crates/weaver-common/src/lexicons/sh/weaver/edit/cursor.rs
··· 1 + // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 + //!Definitions for the `sh.weaver.edit.cursor` namespace. 3 + use atrium_api::types::TryFromUnknown; 4 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 5 + #[serde(rename_all = "camelCase")] 6 + pub struct RecordData { 7 + pub container: ContainerId, 8 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 9 + pub id: core::option::Option<Id>, 10 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 11 + pub side: core::option::Option<CursorSide>, 12 + } 13 + pub type Record = atrium_api::types::Object<RecordData>; 14 + impl From<atrium_api::types::Unknown> for RecordData { 15 + fn from(value: atrium_api::types::Unknown) -> Self { 16 + Self::try_from_unknown(value).unwrap() 17 + } 18 + } 19 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 20 + #[serde(rename_all = "camelCase")] 21 + pub struct ContainerIdData { 22 + pub value: atrium_api::types::Union<ContainerIdValueRefs>, 23 + } 24 + pub type ContainerId = atrium_api::types::Object<ContainerIdData>; 25 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 26 + #[serde(rename_all = "camelCase")] 27 + pub struct CursorSideData { 28 + ///The side of an item the cursor is on (left = -1, right = 1, middle = 0) 29 + pub value: i64, 30 + } 31 + pub type CursorSide = atrium_api::types::Object<CursorSideData>; 32 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 33 + #[serde(rename_all = "camelCase")] 34 + pub struct IdData { 35 + pub counter: i64, 36 + pub peer: i64, 37 + } 38 + pub type Id = atrium_api::types::Object<IdData>; 39 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 40 + #[serde(rename_all = "camelCase")] 41 + pub struct NormalContainerIdData { 42 + pub container_type: String, 43 + pub counter: i64, 44 + pub peer: i64, 45 + } 46 + pub type NormalContainerId = atrium_api::types::Object<NormalContainerIdData>; 47 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 48 + #[serde(rename_all = "camelCase")] 49 + pub struct RootContainerIdData { 50 + pub container_type: String, 51 + pub name: String, 52 + } 53 + pub type RootContainerId = atrium_api::types::Object<RootContainerIdData>; 54 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 55 + #[serde(tag = "$type")] 56 + pub enum ContainerIdValueRefs { 57 + #[serde(rename = "sh.weaver.edit.cursor#normalContainerId")] 58 + NormalContainerId(Box<NormalContainerId>), 59 + #[serde(rename = "sh.weaver.edit.cursor#rootContainerId")] 60 + RootContainerId(Box<RootContainerId>), 61 + }
+28
crates/weaver-common/src/lexicons/sh/weaver/edit/defs.rs
··· 1 + // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 + //!Definitions for the `sh.weaver.edit.defs` namespace. 3 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 4 + #[serde(rename_all = "camelCase")] 5 + pub struct DocRefData { 6 + pub value: atrium_api::types::Union<DocRefValueRefs>, 7 + } 8 + pub type DocRef = atrium_api::types::Object<DocRefData>; 9 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 10 + #[serde(rename_all = "camelCase")] 11 + pub struct EntryRefData { 12 + pub notebook: crate::com::atproto::repo::strong_ref::Main, 13 + } 14 + pub type EntryRef = atrium_api::types::Object<EntryRefData>; 15 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 16 + #[serde(rename_all = "camelCase")] 17 + pub struct NotebookRefData { 18 + pub notebook: crate::com::atproto::repo::strong_ref::Main, 19 + } 20 + pub type NotebookRef = atrium_api::types::Object<NotebookRefData>; 21 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 22 + #[serde(tag = "$type")] 23 + pub enum DocRefValueRefs { 24 + #[serde(rename = "sh.weaver.edit.defs#notebookRef")] 25 + NotebookRef(Box<NotebookRef>), 26 + #[serde(rename = "sh.weaver.edit.defs#entryRef")] 27 + EntryRef(Box<EntryRef>), 28 + }
+16
crates/weaver-common/src/lexicons/sh/weaver/edit/diff.rs
··· 1 + // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 + //!Definitions for the `sh.weaver.edit.diff` namespace. 3 + use atrium_api::types::TryFromUnknown; 4 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 5 + #[serde(rename_all = "camelCase")] 6 + pub struct RecordData { 7 + pub doc: crate::sh::weaver::edit::defs::DocRef, 8 + pub root: crate::com::atproto::repo::strong_ref::Main, 9 + pub snapshot: atrium_api::types::BlobRef, 10 + } 11 + pub type Record = atrium_api::types::Object<RecordData>; 12 + impl From<atrium_api::types::Unknown> for RecordData { 13 + fn from(value: atrium_api::types::Unknown) -> Self { 14 + Self::try_from_unknown(value).unwrap() 15 + } 16 + }
+17
crates/weaver-common/src/lexicons/sh/weaver/edit/root.rs
··· 1 + // @generated - This file is generated by esquema-codegen (forked from atrium-codegen). DO NOT EDIT. 2 + //!Definitions for the `sh.weaver.edit.root` namespace. 3 + use atrium_api::types::TryFromUnknown; 4 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 5 + #[serde(rename_all = "camelCase")] 6 + pub struct RecordData { 7 + pub cid: atrium_api::types::string::Cid, 8 + pub doc: crate::sh::weaver::edit::defs::DocRef, 9 + pub snapshot: atrium_api::types::BlobRef, 10 + pub uri: String, 11 + } 12 + pub type Record = atrium_api::types::Object<RecordData>; 13 + impl From<atrium_api::types::Unknown> for RecordData { 14 + fn from(value: atrium_api::types::Unknown) -> Self { 15 + Self::try_from_unknown(value).unwrap() 16 + } 17 + }
+5 -2
crates/weaver-common/src/lexicons/sh/weaver/notebook/book.rs
··· 5 5 #[serde(rename_all = "camelCase")] 6 6 pub struct RecordData { 7 7 pub authors: crate::sh::weaver::notebook::defs::AuthorListView, 8 - pub cid: atrium_api::types::string::Cid, 8 + ///Client-declared timestamp when this was originally created. 9 9 #[serde(skip_serializing_if = "core::option::Option::is_none")] 10 10 pub created_at: core::option::Option<atrium_api::types::string::Datetime>, 11 11 pub entry_list: Vec<crate::sh::weaver::notebook::defs::BookEntryView>, 12 - pub uri: String, 12 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 13 + pub tags: core::option::Option<crate::sh::weaver::notebook::defs::Tags>, 14 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 15 + pub title: core::option::Option<crate::sh::weaver::notebook::defs::Title>, 13 16 } 14 17 pub type Record = atrium_api::types::Object<RecordData>; 15 18 impl From<atrium_api::types::Unknown> for RecordData {
+23
crates/weaver-common/src/lexicons/sh/weaver/notebook/defs.rs
··· 40 40 pub record: atrium_api::types::Unknown, 41 41 #[serde(skip_serializing_if = "core::option::Option::is_none")] 42 42 pub rendered_view: core::option::Option<RenderedView>, 43 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 44 + pub tags: core::option::Option<Tags>, 45 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 46 + pub title: core::option::Option<Title>, 43 47 pub uri: String, 44 48 } 45 49 pub type EntryView = atrium_api::types::Object<EntryViewData>; 50 + #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 51 + #[serde(rename_all = "camelCase")] 52 + pub struct NotebookViewData { 53 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 54 + pub authors: core::option::Option<AuthorListView>, 55 + pub cid: atrium_api::types::string::Cid, 56 + pub indexed_at: atrium_api::types::string::Datetime, 57 + pub record: atrium_api::types::Unknown, 58 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 59 + pub tags: core::option::Option<Tags>, 60 + #[serde(skip_serializing_if = "core::option::Option::is_none")] 61 + pub title: core::option::Option<Title>, 62 + pub uri: String, 63 + } 64 + pub type NotebookView = atrium_api::types::Object<NotebookViewData>; 46 65 ///View of a rendered and cached notebook entry 47 66 #[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq, Eq)] 48 67 #[serde(rename_all = "camelCase")] ··· 52 71 pub html: atrium_api::types::BlobRef, 53 72 } 54 73 pub type RenderedView = atrium_api::types::Object<RenderedViewData>; 74 + ///An array of tags associated with the notebook entry. Tags can help categorize and organize entries. 75 + pub type Tags = Vec<String>; 76 + ///The title of the notebook entry. 77 + pub type Title = String;
+4 -9
crates/weaver-common/src/lexicons/sh/weaver/notebook/entry.rs
··· 6 6 pub struct RecordData { 7 7 ///The content of the notebook entry. This should be some flavor of Markdown. 8 8 pub content: String, 9 - pub created_at: CreatedAt, 9 + ///Client-declared timestamp when this was originally created. 10 + pub created_at: atrium_api::types::string::Datetime, 10 11 ///The set of images, if any, embedded in the notebook entry. 11 12 #[serde(skip_serializing_if = "core::option::Option::is_none")] 12 13 pub images: core::option::Option<crate::sh::weaver::embed::images::Main>, 13 14 #[serde(skip_serializing_if = "core::option::Option::is_none")] 14 - pub tags: core::option::Option<Tags>, 15 - pub title: Title, 15 + pub tags: core::option::Option<crate::sh::weaver::notebook::defs::Tags>, 16 + pub title: crate::sh::weaver::notebook::defs::Title, 16 17 } 17 18 pub type Record = atrium_api::types::Object<RecordData>; 18 19 impl From<atrium_api::types::Unknown> for RecordData { ··· 20 21 Self::try_from_unknown(value).unwrap() 21 22 } 22 23 } 23 - ///The date and time when the notebook entry was created. This is used for sorting and displaying the entry's creation date. 24 - pub type CreatedAt = String; 25 - ///An array of tags associated with the notebook entry. Tags can help categorize and organize entries. 26 - pub type Tags = Vec<String>; 27 - ///The title of the notebook entry. 28 - pub type Title = String;
+3
crates/weaver-common/src/lib.rs
··· 1 1 pub mod agent; 2 2 pub mod config; 3 3 pub mod error; 4 + /// This filestore is very much not production ready 5 + #[cfg(all(feature = "native", feature = "dev"))] 6 + pub mod filestore; 4 7 pub mod lexicons; 5 8 pub mod oauth; 6 9 pub mod resolver;
+83 -2
crates/weaver-common/src/oauth.rs
··· 28 28 pub http_client: Arc<WeaverHttpClient>, 29 29 } 30 30 31 + pub type NativeBasicOAuthSession = OAuthSession< 32 + DefaultHttpClient, 33 + CommonDidResolver<WeaverHttpClient>, 34 + AtprotoHandleResolver<HickoryDnsTxtResolver, WeaverHttpClient>, 35 + MemoryStore<Did, Session>, 36 + >; 37 + 38 + pub struct NativeWeaverOAuthClient<STATE, SESS> 39 + where 40 + STATE: StateStore + Send + Sync + 'static, 41 + SESS: SessionStore + Send + Sync + 'static, 42 + STATE::Error: std::error::Error + Send + Sync + 'static, 43 + SESS::Error: std::error::Error + Send + Sync + 'static, 44 + { 45 + oauth: WeaverOAuthClient<STATE, SESS>, 46 + pub http_client: Arc<WeaverHttpClient>, 47 + } 31 48 impl NativeOAuthClient { 32 49 pub async fn authorize( 33 50 &self, ··· 45 62 } 46 63 } 47 64 48 - pub type NativeBasicOAuthSession = OAuthSession< 65 + #[cfg(all(feature = "native", feature = "dev"))] 66 + impl 67 + NativeWeaverOAuthClient< 68 + crate::filestore::SimpleJsonFileSessionStore<std::path::PathBuf>, 69 + crate::filestore::SimpleJsonFileSessionStore<std::path::PathBuf>, 70 + > 71 + { 72 + pub async fn authorize( 73 + &self, 74 + input: impl AsRef<str>, 75 + options: AuthorizeOptions, 76 + ) -> Result<String, atrium_oauth::Error> { 77 + self.oauth.authorize(input, options).await 78 + } 79 + 80 + pub async fn callback( 81 + &self, 82 + params: CallbackParams, 83 + ) -> Result<(WeaverOAuthSession, Option<String>), atrium_oauth::Error> { 84 + self.oauth.callback(params).await 85 + } 86 + 87 + pub async fn restore(&self, did: &Did) -> Result<WeaverOAuthSession, atrium_oauth::Error> { 88 + self.oauth.restore(did).await 89 + } 90 + } 91 + 92 + #[cfg(all(feature = "native", feature = "dev"))] 93 + pub type WeaverOAuthSession = OAuthSession< 49 94 DefaultHttpClient, 50 95 CommonDidResolver<WeaverHttpClient>, 51 96 AtprotoHandleResolver<HickoryDnsTxtResolver, WeaverHttpClient>, 52 - MemoryStore<Did, Session>, 97 + crate::filestore::SimpleJsonFileSessionStore<std::path::PathBuf>, 53 98 >; 54 99 55 100 pub type NativeBasicOAuthClient = atrium_oauth::OAuthClient< ··· 135 180 session_store: MemorySessionStore::default(), 136 181 }; 137 182 let client = OAuthClient::new(config)?; 183 + Ok(client) 184 + } 185 + 186 + #[cfg(all(feature = "native", feature = "dev"))] 187 + pub fn test_native_oauth_client() -> Result< 188 + NativeWeaverOAuthClient< 189 + crate::filestore::SimpleJsonFileSessionStore<std::path::PathBuf>, 190 + crate::filestore::SimpleJsonFileSessionStore<std::path::PathBuf>, 191 + >, 192 + atrium_oauth::Error, 193 + > { 194 + use crate::filestore::SimpleJsonFileSessionStore; 195 + 196 + let http_client = Arc::new(WeaverHttpClient::default()); 197 + let config = OAuthClientConfig { 198 + client_metadata: default_native_client_metadata(), 199 + keys: None, 200 + resolver: OAuthResolverConfig { 201 + did_resolver: CommonDidResolver::new(CommonDidResolverConfig { 202 + plc_directory_url: DEFAULT_PLC_DIRECTORY_URL.to_string(), 203 + http_client: Arc::clone(&http_client), 204 + }), 205 + handle_resolver: AtprotoHandleResolver::new(AtprotoHandleResolverConfig { 206 + dns_txt_resolver: HickoryDnsTxtResolver::default(), 207 + http_client: Arc::clone(&http_client), 208 + }), 209 + authorization_server_metadata: Default::default(), 210 + protected_resource_metadata: Default::default(), 211 + }, 212 + state_store: SimpleJsonFileSessionStore::default(), 213 + session_store: SimpleJsonFileSessionStore::default(), 214 + }; 215 + let client = NativeWeaverOAuthClient { 216 + oauth: OAuthClient::new(config)?, 217 + http_client: Arc::clone(&http_client), 218 + }; 138 219 Ok(client) 139 220 } 140 221
+3 -2
crates/weaver-common/src/resolver.rs
··· 18 18 async fn resolve( 19 19 &self, 20 20 query: &str, 21 - ) -> core::result::Result<Vec<String>, Box<dyn std::error::Error + Send + Sync + 'static>> { 21 + ) -> core::result::Result<Vec<String>, Box<dyn std::error::Error + Send + Sync>> { 22 22 Ok(self 23 23 .resolver 24 24 .txt_lookup(query) 25 - .await? 25 + .await 26 + .map_err(crate::error::NetworkError::from)? 26 27 .iter() 27 28 .map(|txt| txt.to_string()) 28 29 .collect())
+2
crates/weaver-renderer/Cargo.toml
··· 13 13 14 14 weaver-workspace-hack = { version = "0.1", path = "../weaver-workspace-hack" } 15 15 compact_string = "0.1.0" 16 + http = "1.3.1" 17 + url = "2.5.4"
+1 -1
crates/weaver-renderer/src/lib.rs
··· 1 1 //! Weaver renderer 2 2 //! 3 - //! This crate works with the weaver-markdown crate to render and optionally upload markdown notebooks to your ATProto PDS. 3 + //! This crate works with the weaver-markdown crate to render and optionally upload markdown notebooks to your Atproto PDS. 4 4 //! 5 5 6 6 pub mod types;
+30 -8
crates/weaver-renderer/src/types.rs
··· 1 1 use atrium_api::types::string::{Cid, Did}; 2 2 use compact_string::CompactString; 3 + use http::Uri; 4 + 5 + pub struct Link { 6 + pub uri: Uri, 7 + pub blob: BlobLink, 8 + } 3 9 4 10 pub type MimeType = CompactString; 5 11 ··· 24 30 25 31 impl std::fmt::Display for BlobLink { 26 32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 27 - write!( 28 - f, 29 - "{}{}/{}@{}", 30 - self.url_prefix(), 31 - self.did().as_str(), 32 - self.cid().as_ref(), 33 - self.mime_type().rsplit('/').next().unwrap() 34 - ) 33 + match self { 34 + BlobLink::PDS { 35 + pds_host, 36 + did, 37 + cid, 38 + mime_type: _, 39 + } => { 40 + write!( 41 + f, 42 + "{}/xrpc/com.atproto.sync.getBlob?did={}&cid={}", 43 + pds_host, 44 + did.as_str(), 45 + cid.as_ref() 46 + ) 47 + } 48 + _ => write!( 49 + f, 50 + "{}{}/{}@{}", 51 + self.url_prefix(), 52 + self.did().as_str(), 53 + self.cid().as_ref(), 54 + self.mime_type().rsplit('/').next().unwrap() 55 + ), 56 + } 35 57 } 36 58 } 37 59
+2 -3
crates/weaver-workspace-hack/Cargo.toml
··· 33 33 group = { version = "0.13", default-features = false, features = ["alloc"] } 34 34 hashbrown = { version = "0.15", features = ["serde"] } 35 35 idna = { version = "1" } 36 - libsqlite3-sys = { version = "0.30", features = ["bundled"] } 37 36 log = { version = "0.4", default-features = false, features = ["std"] } 38 37 memchr = { version = "2", features = ["use_std"] } 39 38 miette = { version = "7", features = ["fancy", "syntect-highlighter"] } ··· 43 42 p384 = { version = "0.13", default-features = false, features = ["ecdsa"] } 44 43 percent-encoding = { version = "2" } 45 44 pkcs8 = { version = "0.10", default-features = false, features = ["pem"] } 46 - proc-macro2 = { version = "1", features = ["span-locations"] } 45 + proc-macro2 = { version = "1" } 47 46 quote = { version = "1" } 48 47 rand_core = { version = "0.6", default-features = false, features = ["std"] } 49 48 reqwest = { version = "0.12", features = ["gzip", "json", "rustls-tls"] } ··· 69 68 diesel_derives = { version = "2", features = ["32-column-tables", "chrono", "postgres", "sqlite", "with-deprecated"] } 70 69 either = { version = "1", features = ["use_std"] } 71 70 hashbrown = { version = "0.15", features = ["serde"] } 72 - proc-macro2 = { version = "1", features = ["span-locations"] } 71 + proc-macro2 = { version = "1" } 73 72 quote = { version = "1" } 74 73 serde = { version = "1", features = ["alloc", "derive"] } 75 74 syn = { version = "2", features = ["extra-traits", "fold", "full", "visit", "visit-mut"] }
+11 -3
lexicon-codegen.sh
··· 2 2 3 3 4 4 #cargo install esquema-cli --locked --git https://github.com/fatfingers23/esquema.git 5 + 5 6 rm -rf ./target/lexicons 6 7 mkdir -p ./target/lexicons 8 + cd target 9 + git clone -n --depth=1 --filter=tree:0 \ 10 + https://github.com/bluesky-social/atproto.git 11 + cd atproto 12 + git sparse-checkout set --no-cone /lexicons 13 + git checkout 14 + cd .. 7 15 8 - cp -r ./lexicons ./target/lexicons 9 - cp -r ./atproto/lexicons ./target/lexicons 16 + cp -r ../lexicons ./ 17 + cp -r ./atproto/lexicons ./ 10 18 11 19 12 - ~/.cargo/bin/esquema-cli generate local --lexdir ./target/lexicons/ --outdir ./crates/weaver-common/src/ --module lexicons 20 + ~/.cargo/bin/esquema-cli generate local --lexdir ./lexicons/ --outdir ../crates/weaver-common/src/ --module lexicons
+81
lexicons/sh/weaver/edit/cursor.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.cursor", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "An edit record for a notebook.", 8 + "key": "tid", 9 + "record": { 10 + "type": "object", 11 + "required": ["container", "die"], 12 + "properties": { 13 + "id": { 14 + "type": "ref", 15 + "ref": "#id" 16 + }, 17 + "container": { 18 + "type": "ref", 19 + "ref": "#containerId" 20 + }, 21 + "side": { 22 + "type": "ref", 23 + "ref": "#cursorSide" 24 + } 25 + } 26 + } 27 + }, 28 + "id": { 29 + "type": "object", 30 + "required": ["peer", "counter"], 31 + "properties": { 32 + "peer": { "type": "integer" }, 33 + "counter": { "type": "integer" } 34 + } 35 + }, 36 + "cursorSide": { 37 + "type": "object", 38 + "required": ["value"], 39 + "properties": { 40 + "value": { 41 + "type": "integer", 42 + "description": "The side of an item the cursor is on (left = -1, right = 1, middle = 0)", 43 + "enum": [-1, 0, 1] 44 + } 45 + } 46 + }, 47 + "containerId": { 48 + "type": "object", 49 + "required": ["value"], 50 + "properties": { 51 + "value": { 52 + "type": "union", 53 + "refs": ["#normalContainerId", "#rootContainerId"] 54 + } 55 + } 56 + }, 57 + "normalContainerId": { 58 + "type": "object", 59 + "required": ["peer", "counter", "container_type"], 60 + "properties": { 61 + "peer": { "type": "integer" }, 62 + "counter": { "type": "integer" }, 63 + "container_type": { 64 + "type": "string", 65 + "enum": ["Map", "List", "Text", "Tree", "MovableList", "Counter"] 66 + } 67 + } 68 + }, 69 + "rootContainerId": { 70 + "type": "object", 71 + "required": ["name", "container_type"], 72 + "properties": { 73 + "name": { "type": "string" }, 74 + "container_type": { 75 + "type": "string", 76 + "enum": ["Map", "List", "Text", "Tree", "MovableList", "Counter"] 77 + } 78 + } 79 + } 80 + } 81 + }
+36
lexicons/sh/weaver/edit/defs.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.defs", 4 + "defs": { 5 + "docRef": { 6 + "type": "object", 7 + "required": ["value"], 8 + "properties": { 9 + "value": { 10 + "type": "union", 11 + "refs": ["#notebookRef", "#entryRef"] 12 + } 13 + } 14 + }, 15 + "notebookRef": { 16 + "type": "object", 17 + "required": ["notebook"], 18 + "properties": { 19 + "notebook": { 20 + "type": "ref", 21 + "ref": "com.atproto.repo.strongRef" 22 + } 23 + } 24 + }, 25 + "entryRef": { 26 + "type": "object", 27 + "required": ["notebook"], 28 + "properties": { 29 + "notebook": { 30 + "type": "ref", 31 + "ref": "com.atproto.repo.strongRef" 32 + } 33 + } 34 + } 35 + } 36 + }
+30
lexicons/sh/weaver/edit/diff.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.diff", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "An edit record for a notebook.", 8 + "key": "tid", 9 + "record": { 10 + "type": "object", 11 + "required": ["snapshot", "root", "doc"], 12 + "properties": { 13 + "snapshot": { 14 + "type": "blob", 15 + "accept": ["*/*"], 16 + "maxSize": 3000000 17 + }, 18 + "root": { 19 + "type": "ref", 20 + "ref": "com.atproto.repo.strongRef" 21 + }, 22 + "doc": { 23 + "type": "ref", 24 + "ref": "sh.weaver.edit.defs#docRef" 25 + } 26 + } 27 + } 28 + } 29 + } 30 + }
+28
lexicons/sh/weaver/edit/root.json
··· 1 + { 2 + "lexicon": 1, 3 + "id": "sh.weaver.edit.root", 4 + "defs": { 5 + "main": { 6 + "type": "record", 7 + "description": "The starting point for edit history on a notebook.", 8 + "key": "tid", 9 + "record": { 10 + "type": "object", 11 + "required": ["cid", "uri", "doc", "snapshot"], 12 + "properties": { 13 + "uri": { "type": "string", "format": "at-uri" }, 14 + "cid": { "type": "string", "format": "cid" }, 15 + "snapshot": { 16 + "type": "blob", 17 + "accept": ["*/*"], 18 + "maxSize": 30000000 19 + }, 20 + "doc": { 21 + "type": "ref", 22 + "ref": "sh.weaver.edit.defs#docRef" 23 + } 24 + } 25 + } 26 + } 27 + } 28 + }
+8 -4
lexicons/sh/weaver/notebook/book.json
··· 8 8 "key": "tid", 9 9 "record": { 10 10 "type": "object", 11 - "required": ["cid", "uri", "authors", "entryList"], 11 + "required": ["authors", "entryList"], 12 12 "properties": { 13 - "uri": { "type": "string", "format": "at-uri" }, 14 - "cid": { "type": "string", "format": "cid" }, 13 + "title": { "type": "ref", "ref": "sh.weaver.notebook.defs#title" }, 14 + "tags": { "type": "ref", "ref": "sh.weaver.notebook.defs#tags" }, 15 15 "authors": { 16 16 "type": "ref", 17 17 "ref": "sh.weaver.notebook.defs#authorListView" ··· 23 23 "ref": "sh.weaver.notebook.defs#bookEntryView" 24 24 } 25 25 }, 26 - "createdAt": { "type": "string", "format": "datetime" } 26 + "createdAt": { 27 + "type": "string", 28 + "format": "datetime", 29 + "description": "Client-declared timestamp when this was originally created." 30 + } 27 31 } 28 32 } 29 33 }
+33
lexicons/sh/weaver/notebook/defs.json
··· 2 2 "lexicon": 1, 3 3 "id": "sh.weaver.notebook.defs", 4 4 "defs": { 5 + "notebookView": { 6 + "type": "object", 7 + "required": ["uri", "cid", "author", "record", "indexedAt"], 8 + 9 + "properties": { 10 + "title": { "type": "ref", "ref": "#title" }, 11 + "tags": { "type": "ref", "ref": "#tags" }, 12 + "uri": { "type": "string", "format": "at-uri" }, 13 + "cid": { "type": "string", "format": "cid" }, 14 + "authors": { 15 + "type": "ref", 16 + "ref": "#authorListView" 17 + }, 18 + "record": { "type": "unknown" }, 19 + "indexedAt": { "type": "string", "format": "datetime" } 20 + } 21 + }, 5 22 "entryView": { 6 23 "type": "object", 7 24 "required": ["uri", "cid", "author", "record", "indexedAt"], 8 25 9 26 "properties": { 27 + "title": { "type": "ref", "ref": "#title" }, 28 + "tags": { "type": "ref", "ref": "#tags" }, 10 29 "uri": { "type": "string", "format": "at-uri" }, 11 30 "cid": { "type": "string", "format": "cid" }, 12 31 "authors": { ··· 79 98 "ref": "#entryView" 80 99 } 81 100 } 101 + }, 102 + "title": { 103 + "type": "string", 104 + "maxLength": 420, 105 + "description": "The title of the notebook entry." 106 + }, 107 + "tags": { 108 + "type": "array", 109 + "items": { 110 + "type": "string", 111 + "maxLength": 64 112 + }, 113 + "maxLength": 10, 114 + "description": "An array of tags associated with the notebook entry. Tags can help categorize and organize entries." 82 115 } 83 116 } 84 117 }
+5 -24
lexicons/sh/weaver/notebook/entry.json
··· 10 10 "type": "object", 11 11 "required": ["content", "title", "createdAt"], 12 12 "properties": { 13 - "title": { "type": "ref", "ref": "#title" }, 14 - "tags": { "type": "ref", "ref": "#tags" }, 13 + "title": { "type": "ref", "ref": "sh.weaver.notebook.defs#title" }, 14 + "tags": { "type": "ref", "ref": "sh.weaver.notebook.defs#tags" }, 15 15 16 16 "content": { 17 17 "type": "string", ··· 20 20 }, 21 21 22 22 "createdAt": { 23 - "type": "ref", 24 - "ref": "#createdAt" 23 + "type": "string", 24 + "format": "datetime", 25 + "description": "Client-declared timestamp when this was originally created." 25 26 }, 26 27 "images": { 27 28 "type": "ref", ··· 30 31 } 31 32 } 32 33 } 33 - }, 34 - 35 - "createdAt": { 36 - "type": "string", 37 - "format": "datetime", 38 - "description": "The date and time when the notebook entry was created. This is used for sorting and displaying the entry's creation date." 39 - }, 40 - "title": { 41 - "type": "string", 42 - "maxLength": 420, 43 - "description": "The title of the notebook entry." 44 - }, 45 - "tags": { 46 - "type": "array", 47 - "items": { 48 - "type": "string", 49 - "maxLength": 64 50 - }, 51 - "maxLength": 10, 52 - "description": "An array of tags associated with the notebook entry. Tags can help categorize and organize entries." 53 34 } 54 35 } 55 36 }
+8
test.html
··· 3 3 <head> 4 4 <meta charset="utf-8"> 5 5 </head> 6 + <script> 7 + console.log( window.location.href ); // whatever your current location href is 8 + window.history.replaceState( {} , 'foo', './LICENSE' ); 9 + console.log( window.location.href ); // oh, hey, it replaced the path with /foo 10 + 11 + 12 + </script> 6 13 <body> 7 14 <h1>Main Title &amp; &quot;Special Chars&quot;</h1> 8 15 <p>This is a paragraph with <em>emphasis</em>, <strong>strong emphasis</strong>, <del>strikethrough</del>, and <code>inline code</code>. ··· 15 22 </blockquote> 16 23 </blockquote> 17 24 <hr /> 25 + 18 26 <h2>Lists and Links</h2> 19 27 <ul> 20 28 <li><p>Unordered item 1</p>