Monorepo for wisp.place. A static site hosting service built on top of the AT Protocol.

lexicon work i shouldve done ages ago

+251 -382
+88 -255
cli/Cargo.lock
··· 3 version = 4 4 5 [[package]] 6 - name = "abnf" 7 - version = "0.13.0" 8 - source = "registry+https://github.com/rust-lang/crates.io-index" 9 - checksum = "087113bd50d9adce24850eed5d0476c7d199d532fce8fab5173650331e09033a" 10 - dependencies = [ 11 - "abnf-core", 12 - "nom", 13 - ] 14 - 15 - [[package]] 16 - name = "abnf-core" 17 - version = "0.5.0" 18 - source = "registry+https://github.com/rust-lang/crates.io-index" 19 - checksum = "c44e09c43ae1c368fb91a03a566472d0087c26cf7e1b9e8e289c14ede681dd7d" 20 - dependencies = [ 21 - "nom", 22 - ] 23 - 24 - [[package]] 25 name = "addr2line" 26 version = "0.25.1" 27 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 71 dependencies = [ 72 "alloc-no-stdlib", 73 ] 74 75 [[package]] 76 name = "android_system_properties" ··· 379 ] 380 381 [[package]] 382 - name = "btree-range-map" 383 - version = "0.7.2" 384 - source = "registry+https://github.com/rust-lang/crates.io-index" 385 - checksum = "1be5c9672446d3800bcbcaabaeba121fe22f1fb25700c4562b22faf76d377c33" 386 - dependencies = [ 387 - "btree-slab", 388 - "cc-traits", 389 - "range-traits", 390 - "serde", 391 - "slab", 392 - ] 393 - 394 - [[package]] 395 - name = "btree-slab" 396 - version = "0.6.1" 397 - source = "registry+https://github.com/rust-lang/crates.io-index" 398 - checksum = "7a2b56d3029f075c4fa892428a098425b86cef5c89ae54073137ece416aef13c" 399 - dependencies = [ 400 - "cc-traits", 401 - "slab", 402 - "smallvec", 403 - ] 404 - 405 - [[package]] 406 name = "buf_redux" 407 version = "0.8.4" 408 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 450 dependencies = [ 451 "find-msvc-tools", 452 "shlex", 453 - ] 454 - 455 - [[package]] 456 - name = "cc-traits" 457 - version = "2.0.0" 458 - source = "registry+https://github.com/rust-lang/crates.io-index" 459 - checksum = "060303ef31ef4a522737e1b1ab68c67916f2a787bb2f4f54f383279adba962b5" 460 - dependencies = [ 461 - "slab", 462 ] 463 464 [[package]] ··· 881 checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" 882 dependencies = [ 883 "powerfmt", 884 - "serde_core", 885 ] 886 887 [[package]] ··· 954 "quote", 955 "syn 2.0.111", 956 ] 957 - 958 - [[package]] 959 - name = "dyn-clone" 960 - version = "1.0.20" 961 - source = "registry+https://github.com/rust-lang/crates.io-index" 962 - checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555" 963 964 [[package]] 965 name = "ecdsa" ··· 1101 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 1102 1103 [[package]] 1104 name = "form_urlencoded" 1105 version = "1.2.2" 1106 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1365 "futures-core", 1366 "futures-sink", 1367 "http", 1368 - "indexmap 2.12.1", 1369 "slab", 1370 "tokio", 1371 "tokio-util", ··· 1394 1395 [[package]] 1396 name = "hashbrown" 1397 - version = "0.12.3" 1398 source = "registry+https://github.com/rust-lang/crates.io-index" 1399 - checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 1400 1401 [[package]] 1402 name = "hashbrown" 1403 - version = "0.14.5" 1404 source = "registry+https://github.com/rust-lang/crates.io-index" 1405 - checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1406 1407 [[package]] 1408 name = "hashbrown" ··· 1449 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1450 1451 [[package]] 1452 - name = "hex_fmt" 1453 - version = "0.3.0" 1454 - source = "registry+https://github.com/rust-lang/crates.io-index" 1455 - checksum = "b07f60793ff0a4d9cef0f18e63b5357e06209987153a64648c972c1e5aff336f" 1456 - 1457 - [[package]] 1458 name = "hickory-proto" 1459 version = "0.24.4" 1460 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1789 1790 [[package]] 1791 name = "indexmap" 1792 - version = "1.9.3" 1793 - source = "registry+https://github.com/rust-lang/crates.io-index" 1794 - checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 1795 - dependencies = [ 1796 - "autocfg", 1797 - "hashbrown 0.12.3", 1798 - "serde", 1799 - ] 1800 - 1801 - [[package]] 1802 - name = "indexmap" 1803 version = "2.12.1" 1804 source = "registry+https://github.com/rust-lang/crates.io-index" 1805 checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" 1806 dependencies = [ 1807 "equivalent", 1808 "hashbrown 0.16.1", 1809 - "serde", 1810 - "serde_core", 1811 ] 1812 1813 [[package]] ··· 1824 ] 1825 1826 [[package]] 1827 - name = "indoc" 1828 - version = "2.0.7" 1829 - source = "registry+https://github.com/rust-lang/crates.io-index" 1830 - checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" 1831 - dependencies = [ 1832 - "rustversion", 1833 - ] 1834 - 1835 - [[package]] 1836 name = "inventory" 1837 version = "0.3.21" 1838 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1900 1901 [[package]] 1902 name = "jacquard" 1903 - version = "0.9.4" 1904 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 1905 dependencies = [ 1906 "bytes", 1907 "getrandom 0.2.16", ··· 1917 "regex", 1918 "regex-lite", 1919 "reqwest", 1920 - "ring", 1921 "serde", 1922 "serde_html_form", 1923 "serde_json", ··· 1931 1932 [[package]] 1933 name = "jacquard-api" 1934 - version = "0.9.2" 1935 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 1936 dependencies = [ 1937 "bon", 1938 "bytes", ··· 1950 1951 [[package]] 1952 name = "jacquard-common" 1953 - version = "0.9.2" 1954 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 1955 dependencies = [ 1956 "base64 0.22.1", 1957 "bon", 1958 "bytes", 1959 "chrono", 1960 "ciborium", 1961 "cid", 1962 "futures", 1963 "getrandom 0.2.16", 1964 "getrandom 0.3.4", 1965 "http", 1966 "ipld-core", 1967 "k256", 1968 - "langtag", 1969 "miette", 1970 "multibase", 1971 "multihash", 1972 "n0-future 0.1.3", 1973 "ouroboros", 1974 "p256", 1975 "postcard", 1976 "rand 0.9.2", 1977 "regex", 1978 "regex-lite", 1979 "reqwest", 1980 - "ring", 1981 "serde", 1982 "serde_bytes", 1983 "serde_html_form", ··· 1985 "serde_json", 1986 "signature", 1987 "smol_str", 1988 "thiserror 2.0.17", 1989 "tokio", 1990 "tokio-tungstenite-wasm", ··· 1995 1996 [[package]] 1997 name = "jacquard-derive" 1998 - version = "0.9.4" 1999 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 2000 dependencies = [ 2001 "heck 0.5.0", 2002 "jacquard-lexicon", ··· 2007 2008 [[package]] 2009 name = "jacquard-identity" 2010 - version = "0.9.2" 2011 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 2012 dependencies = [ 2013 "bon", 2014 "bytes", ··· 2018 "jacquard-common", 2019 "jacquard-lexicon", 2020 "miette", 2021 - "mini-moka", 2022 "n0-future 0.1.3", 2023 "percent-encoding", 2024 "reqwest", 2025 - "ring", 2026 "serde", 2027 "serde_html_form", 2028 "serde_json", ··· 2035 2036 [[package]] 2037 name = "jacquard-lexicon" 2038 - version = "0.9.2" 2039 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 2040 dependencies = [ 2041 "cid", 2042 "dashmap", ··· 2061 2062 [[package]] 2063 name = "jacquard-oauth" 2064 - version = "0.9.2" 2065 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 2066 dependencies = [ 2067 "base64 0.22.1", 2068 "bytes", ··· 2077 "miette", 2078 "p256", 2079 "rand 0.8.5", 2080 - "ring", 2081 "rouille", 2082 "serde", 2083 "serde_html_form", ··· 2172 ] 2173 2174 [[package]] 2175 - name = "langtag" 2176 - version = "0.4.0" 2177 - source = "registry+https://github.com/rust-lang/crates.io-index" 2178 - checksum = "9ecb4c689a30e48ebeaa14237f34037e300dd072e6ad21a9ec72e810ff3c6600" 2179 - dependencies = [ 2180 - "serde", 2181 - "static-regular-grammar", 2182 - "thiserror 1.0.69", 2183 - ] 2184 - 2185 - [[package]] 2186 name = "lazy_static" 2187 version = "1.5.0" 2188 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2282 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" 2283 2284 [[package]] 2285 name = "markup5ever" 2286 version = "0.12.1" 2287 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2386 ] 2387 2388 [[package]] 2389 - name = "mini-moka" 2390 version = "0.10.99" 2391 - source = "git+https://tangled.org/nekomimi.pet/jacquard#69a1552424ffa439ea1022aa8e3f311ed77ab4df" 2392 dependencies = [ 2393 "crossbeam-channel", 2394 "crossbeam-utils", ··· 2398 "triomphe", 2399 "web-time", 2400 ] 2401 - 2402 - [[package]] 2403 - name = "minimal-lexical" 2404 - version = "0.2.1" 2405 - source = "registry+https://github.com/rust-lang/crates.io-index" 2406 - checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 2407 2408 [[package]] 2409 name = "miniz_oxide" ··· 2468 ] 2469 2470 [[package]] 2471 name = "n0-future" 2472 version = "0.1.3" 2473 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2520 version = "1.0.6" 2521 source = "registry+https://github.com/rust-lang/crates.io-index" 2522 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 2523 - 2524 - [[package]] 2525 - name = "nom" 2526 - version = "7.1.3" 2527 - source = "registry+https://github.com/rust-lang/crates.io-index" 2528 - checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 2529 - dependencies = [ 2530 - "memchr", 2531 - "minimal-lexical", 2532 - ] 2533 2534 [[package]] 2535 name = "nu-ansi-term" ··· 2706 checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" 2707 2708 [[package]] 2709 name = "p256" 2710 version = "0.13.2" 2711 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2931 ] 2932 2933 [[package]] 2934 - name = "proc-macro-error" 2935 - version = "1.0.4" 2936 - source = "registry+https://github.com/rust-lang/crates.io-index" 2937 - checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" 2938 - dependencies = [ 2939 - "proc-macro-error-attr", 2940 - "proc-macro2", 2941 - "quote", 2942 - "syn 1.0.109", 2943 - "version_check", 2944 - ] 2945 - 2946 - [[package]] 2947 - name = "proc-macro-error-attr" 2948 - version = "1.0.4" 2949 - source = "registry+https://github.com/rust-lang/crates.io-index" 2950 - checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" 2951 - dependencies = [ 2952 - "proc-macro2", 2953 - "quote", 2954 - "version_check", 2955 - ] 2956 - 2957 - [[package]] 2958 name = "proc-macro2" 2959 version = "1.0.103" 2960 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3112 ] 3113 3114 [[package]] 3115 - name = "range-traits" 3116 - version = "0.3.2" 3117 - source = "registry+https://github.com/rust-lang/crates.io-index" 3118 - checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab" 3119 - 3120 - [[package]] 3121 name = "redox_syscall" 3122 version = "0.5.18" 3123 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3138 ] 3139 3140 [[package]] 3141 - name = "ref-cast" 3142 - version = "1.0.25" 3143 - source = "registry+https://github.com/rust-lang/crates.io-index" 3144 - checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" 3145 - dependencies = [ 3146 - "ref-cast-impl", 3147 - ] 3148 - 3149 - [[package]] 3150 - name = "ref-cast-impl" 3151 - version = "1.0.25" 3152 - source = "registry+https://github.com/rust-lang/crates.io-index" 3153 - checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" 3154 - dependencies = [ 3155 - "proc-macro2", 3156 - "quote", 3157 - "syn 2.0.111", 3158 - ] 3159 - 3160 - [[package]] 3161 name = "regex" 3162 version = "1.12.2" 3163 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3429 ] 3430 3431 [[package]] 3432 - name = "schemars" 3433 - version = "0.9.0" 3434 - source = "registry+https://github.com/rust-lang/crates.io-index" 3435 - checksum = "4cd191f9397d57d581cddd31014772520aa448f65ef991055d7f61582c65165f" 3436 - dependencies = [ 3437 - "dyn-clone", 3438 - "ref-cast", 3439 - "serde", 3440 - "serde_json", 3441 - ] 3442 - 3443 - [[package]] 3444 - name = "schemars" 3445 - version = "1.1.0" 3446 - source = "registry+https://github.com/rust-lang/crates.io-index" 3447 - checksum = "9558e172d4e8533736ba97870c4b2cd63f84b382a3d6eb063da41b91cce17289" 3448 - dependencies = [ 3449 - "dyn-clone", 3450 - "ref-cast", 3451 - "serde", 3452 - "serde_json", 3453 - ] 3454 - 3455 - [[package]] 3456 name = "scoped-tls" 3457 version = "1.0.1" 3458 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3555 3556 [[package]] 3557 name = "serde_html_form" 3558 - version = "0.2.8" 3559 source = "registry+https://github.com/rust-lang/crates.io-index" 3560 - checksum = "b2f2d7ff8a2140333718bb329f5c40fc5f0865b84c426183ce14c97d2ab8154f" 3561 dependencies = [ 3562 "form_urlencoded", 3563 - "indexmap 2.12.1", 3564 "itoa", 3565 - "ryu", 3566 "serde_core", 3567 ] 3568 ··· 3634 "base64 0.22.1", 3635 "chrono", 3636 "hex", 3637 - "indexmap 1.9.3", 3638 - "indexmap 2.12.1", 3639 - "schemars 0.9.0", 3640 - "schemars 1.1.0", 3641 "serde_core", 3642 "serde_json", 3643 "serde_with_macros", ··· 3811 version = "1.2.1" 3812 source = "registry+https://github.com/rust-lang/crates.io-index" 3813 checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 3814 - 3815 - [[package]] 3816 - name = "static-regular-grammar" 3817 - version = "2.0.2" 3818 - source = "registry+https://github.com/rust-lang/crates.io-index" 3819 - checksum = "4f4a6c40247579acfbb138c3cd7de3dab113ab4ac6227f1b7de7d626ee667957" 3820 - dependencies = [ 3821 - "abnf", 3822 - "btree-range-map", 3823 - "ciborium", 3824 - "hex_fmt", 3825 - "indoc", 3826 - "proc-macro-error", 3827 - "proc-macro2", 3828 - "quote", 3829 - "serde", 3830 - "sha2", 3831 - "syn 2.0.111", 3832 - "thiserror 1.0.69", 3833 - ] 3834 3835 [[package]] 3836 name = "static_assertions" ··· 4074 checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" 4075 dependencies = [ 4076 "deranged", 4077 - "itoa", 4078 "libc", 4079 "num-conv", 4080 "num_threads", 4081 "powerfmt", 4082 "serde", 4083 "time-core", 4084 - "time-macros", 4085 ] 4086 4087 [[package]] ··· 4089 version = "0.1.6" 4090 source = "registry+https://github.com/rust-lang/crates.io-index" 4091 checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" 4092 - 4093 - [[package]] 4094 - name = "time-macros" 4095 - version = "0.2.24" 4096 - source = "registry+https://github.com/rust-lang/crates.io-index" 4097 - checksum = "30cfb0125f12d9c277f35663a0a33f8c30190f4e4574868a330595412d34ebf3" 4098 - dependencies = [ 4099 - "num-conv", 4100 - "time-core", 4101 - ] 4102 4103 [[package]] 4104 name = "tiny_http" ··· 5184 "tower-http", 5185 "url", 5186 "walkdir", 5187 ] 5188 5189 [[package]]
··· 3 version = 4 4 5 [[package]] 6 name = "addr2line" 7 version = "0.25.1" 8 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 52 dependencies = [ 53 "alloc-no-stdlib", 54 ] 55 + 56 + [[package]] 57 + name = "allocator-api2" 58 + version = "0.2.21" 59 + source = "registry+https://github.com/rust-lang/crates.io-index" 60 + checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" 61 62 [[package]] 63 name = "android_system_properties" ··· 366 ] 367 368 [[package]] 369 name = "buf_redux" 370 version = "0.8.4" 371 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 413 dependencies = [ 414 "find-msvc-tools", 415 "shlex", 416 ] 417 418 [[package]] ··· 835 checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" 836 dependencies = [ 837 "powerfmt", 838 ] 839 840 [[package]] ··· 907 "quote", 908 "syn 2.0.111", 909 ] 910 911 [[package]] 912 name = "ecdsa" ··· 1048 checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 1049 1050 [[package]] 1051 + name = "foldhash" 1052 + version = "0.1.5" 1053 + source = "registry+https://github.com/rust-lang/crates.io-index" 1054 + checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" 1055 + 1056 + [[package]] 1057 name = "form_urlencoded" 1058 version = "1.2.2" 1059 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1318 "futures-core", 1319 "futures-sink", 1320 "http", 1321 + "indexmap", 1322 "slab", 1323 "tokio", 1324 "tokio-util", ··· 1347 1348 [[package]] 1349 name = "hashbrown" 1350 + version = "0.14.5" 1351 source = "registry+https://github.com/rust-lang/crates.io-index" 1352 + checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1353 1354 [[package]] 1355 name = "hashbrown" 1356 + version = "0.15.5" 1357 source = "registry+https://github.com/rust-lang/crates.io-index" 1358 + checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" 1359 + dependencies = [ 1360 + "allocator-api2", 1361 + "equivalent", 1362 + "foldhash", 1363 + ] 1364 1365 [[package]] 1366 name = "hashbrown" ··· 1407 checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1408 1409 [[package]] 1410 name = "hickory-proto" 1411 version = "0.24.4" 1412 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1741 1742 [[package]] 1743 name = "indexmap" 1744 version = "2.12.1" 1745 source = "registry+https://github.com/rust-lang/crates.io-index" 1746 checksum = "0ad4bb2b565bca0645f4d68c5c9af97fba094e9791da685bf83cb5f3ce74acf2" 1747 dependencies = [ 1748 "equivalent", 1749 "hashbrown 0.16.1", 1750 ] 1751 1752 [[package]] ··· 1763 ] 1764 1765 [[package]] 1766 name = "inventory" 1767 version = "0.3.21" 1768 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 1830 1831 [[package]] 1832 name = "jacquard" 1833 + version = "0.9.5" 1834 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1835 dependencies = [ 1836 "bytes", 1837 "getrandom 0.2.16", ··· 1847 "regex", 1848 "regex-lite", 1849 "reqwest", 1850 "serde", 1851 "serde_html_form", 1852 "serde_json", ··· 1860 1861 [[package]] 1862 name = "jacquard-api" 1863 + version = "0.9.5" 1864 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1865 dependencies = [ 1866 "bon", 1867 "bytes", ··· 1879 1880 [[package]] 1881 name = "jacquard-common" 1882 + version = "0.9.5" 1883 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1884 dependencies = [ 1885 "base64 0.22.1", 1886 "bon", 1887 "bytes", 1888 "chrono", 1889 "ciborium", 1890 + "ciborium-io", 1891 "cid", 1892 "futures", 1893 "getrandom 0.2.16", 1894 "getrandom 0.3.4", 1895 + "hashbrown 0.15.5", 1896 "http", 1897 "ipld-core", 1898 "k256", 1899 + "maitake-sync", 1900 "miette", 1901 "multibase", 1902 "multihash", 1903 "n0-future 0.1.3", 1904 "ouroboros", 1905 + "oxilangtag", 1906 "p256", 1907 "postcard", 1908 "rand 0.9.2", 1909 "regex", 1910 + "regex-automata", 1911 "regex-lite", 1912 "reqwest", 1913 "serde", 1914 "serde_bytes", 1915 "serde_html_form", ··· 1917 "serde_json", 1918 "signature", 1919 "smol_str", 1920 + "spin 0.10.0", 1921 "thiserror 2.0.17", 1922 "tokio", 1923 "tokio-tungstenite-wasm", ··· 1928 1929 [[package]] 1930 name = "jacquard-derive" 1931 + version = "0.9.5" 1932 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1933 dependencies = [ 1934 "heck 0.5.0", 1935 "jacquard-lexicon", ··· 1940 1941 [[package]] 1942 name = "jacquard-identity" 1943 + version = "0.9.5" 1944 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1945 dependencies = [ 1946 "bon", 1947 "bytes", ··· 1951 "jacquard-common", 1952 "jacquard-lexicon", 1953 "miette", 1954 + "mini-moka-wasm", 1955 "n0-future 0.1.3", 1956 "percent-encoding", 1957 "reqwest", 1958 "serde", 1959 "serde_html_form", 1960 "serde_json", ··· 1967 1968 [[package]] 1969 name = "jacquard-lexicon" 1970 + version = "0.9.5" 1971 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1972 dependencies = [ 1973 "cid", 1974 "dashmap", ··· 1993 1994 [[package]] 1995 name = "jacquard-oauth" 1996 + version = "0.9.6" 1997 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 1998 dependencies = [ 1999 "base64 0.22.1", 2000 "bytes", ··· 2009 "miette", 2010 "p256", 2011 "rand 0.8.5", 2012 "rouille", 2013 "serde", 2014 "serde_html_form", ··· 2103 ] 2104 2105 [[package]] 2106 name = "lazy_static" 2107 version = "1.5.0" 2108 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2202 checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" 2203 2204 [[package]] 2205 + name = "maitake-sync" 2206 + version = "0.1.2" 2207 + source = "registry+https://github.com/rust-lang/crates.io-index" 2208 + checksum = "6816ab14147f80234c675b80ed6dc4f440d8a1cefc158e766067aedb84c0bcd5" 2209 + dependencies = [ 2210 + "cordyceps", 2211 + "loom", 2212 + "mycelium-bitfield", 2213 + "pin-project", 2214 + "portable-atomic", 2215 + ] 2216 + 2217 + [[package]] 2218 name = "markup5ever" 2219 version = "0.12.1" 2220 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2319 ] 2320 2321 [[package]] 2322 + name = "mini-moka-wasm" 2323 version = "0.10.99" 2324 + source = "git+https://tangled.org/nonbinary.computer/jacquard#5bcf7f8e87324b8e67fc273c678d0490c9c6d15b" 2325 dependencies = [ 2326 "crossbeam-channel", 2327 "crossbeam-utils", ··· 2331 "triomphe", 2332 "web-time", 2333 ] 2334 2335 [[package]] 2336 name = "miniz_oxide" ··· 2395 ] 2396 2397 [[package]] 2398 + name = "mycelium-bitfield" 2399 + version = "0.1.5" 2400 + source = "registry+https://github.com/rust-lang/crates.io-index" 2401 + checksum = "24e0cc5e2c585acbd15c5ce911dff71e1f4d5313f43345873311c4f5efd741cc" 2402 + 2403 + [[package]] 2404 name = "n0-future" 2405 version = "0.1.3" 2406 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2453 version = "1.0.6" 2454 source = "registry+https://github.com/rust-lang/crates.io-index" 2455 checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 2456 2457 [[package]] 2458 name = "nu-ansi-term" ··· 2629 checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52" 2630 2631 [[package]] 2632 + name = "oxilangtag" 2633 + version = "0.1.5" 2634 + source = "registry+https://github.com/rust-lang/crates.io-index" 2635 + checksum = "23f3f87617a86af77fa3691e6350483e7154c2ead9f1261b75130e21ca0f8acb" 2636 + dependencies = [ 2637 + "serde", 2638 + ] 2639 + 2640 + [[package]] 2641 name = "p256" 2642 version = "0.13.2" 2643 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 2863 ] 2864 2865 [[package]] 2866 name = "proc-macro2" 2867 version = "1.0.103" 2868 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3020 ] 3021 3022 [[package]] 3023 name = "redox_syscall" 3024 version = "0.5.18" 3025 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3040 ] 3041 3042 [[package]] 3043 name = "regex" 3044 version = "1.12.2" 3045 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3311 ] 3312 3313 [[package]] 3314 name = "scoped-tls" 3315 version = "1.0.1" 3316 source = "registry+https://github.com/rust-lang/crates.io-index" ··· 3413 3414 [[package]] 3415 name = "serde_html_form" 3416 + version = "0.3.2" 3417 source = "registry+https://github.com/rust-lang/crates.io-index" 3418 + checksum = "2acf96b1d9364968fce46ebb548f1c0e1d7eceae27bdff73865d42e6c7369d94" 3419 dependencies = [ 3420 "form_urlencoded", 3421 + "indexmap", 3422 "itoa", 3423 "serde_core", 3424 ] 3425 ··· 3491 "base64 0.22.1", 3492 "chrono", 3493 "hex", 3494 "serde_core", 3495 "serde_json", 3496 "serde_with_macros", ··· 3664 version = "1.2.1" 3665 source = "registry+https://github.com/rust-lang/crates.io-index" 3666 checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" 3667 3668 [[package]] 3669 name = "static_assertions" ··· 3907 checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" 3908 dependencies = [ 3909 "deranged", 3910 "libc", 3911 "num-conv", 3912 "num_threads", 3913 "powerfmt", 3914 "serde", 3915 "time-core", 3916 ] 3917 3918 [[package]] ··· 3920 version = "0.1.6" 3921 source = "registry+https://github.com/rust-lang/crates.io-index" 3922 checksum = "40868e7c1d2f0b8d73e4a8c7f0ff63af4f6d19be117e90bd73eb1d62cf831c6b" 3923 3924 [[package]] 3925 name = "tiny_http" ··· 5005 "tower-http", 5006 "url", 5007 "walkdir", 5008 + "wisp-lexicons", 5009 + ] 5010 + 5011 + [[package]] 5012 + name = "wisp-lexicons" 5013 + version = "0.1.0" 5014 + dependencies = [ 5015 + "jacquard-common", 5016 + "jacquard-derive", 5017 + "jacquard-lexicon", 5018 + "rustversion", 5019 + "serde", 5020 ] 5021 5022 [[package]]
+8 -7
cli/Cargo.toml
··· 8 place_wisp = [] 9 10 [dependencies] 11 - jacquard = { git = "https://tangled.org/nekomimi.pet/jacquard", features = ["loopback"] } 12 - jacquard-oauth = { git = "https://tangled.org/nekomimi.pet/jacquard" } 13 - jacquard-api = { git = "https://tangled.org/nekomimi.pet/jacquard", features = ["streaming"] } 14 - jacquard-common = { git = "https://tangled.org/nekomimi.pet/jacquard", features = ["websocket"] } 15 - jacquard-identity = { git = "https://tangled.org/nekomimi.pet/jacquard", features = ["dns"] } 16 - jacquard-derive = { git = "https://tangled.org/nekomimi.pet/jacquard" } 17 - jacquard-lexicon = { git = "https://tangled.org/nekomimi.pet/jacquard" } 18 #jacquard = { path = "../../jacquard/crates/jacquard", features = ["loopback"] } 19 #jacquard-oauth = { path = "../../jacquard/crates/jacquard-oauth" } 20 #jacquard-api = { path = "../../jacquard/crates/jacquard-api", features = ["streaming"] }
··· 8 place_wisp = [] 9 10 [dependencies] 11 + jacquard = { git = "https://tangled.org/nonbinary.computer/jacquard", features = ["loopback"] } 12 + jacquard-oauth = { git = "https://tangled.org/nonbinary.computer/jacquard" } 13 + jacquard-api = { git = "https://tangled.org/nonbinary.computer/jacquard", features = ["streaming"] } 14 + jacquard-common = { git = "https://tangled.org/nonbinary.computer/jacquard", features = ["websocket"] } 15 + jacquard-identity = { git = "https://tangled.org/nonbinary.computer/jacquard", features = ["dns"] } 16 + jacquard-derive = { git = "https://tangled.org/nonbinary.computer/jacquard" } 17 + jacquard-lexicon = { git = "https://tangled.org/nonbinary.computer/jacquard" } 18 + wisp-lexicons = { path = "crates/lexicons" } 19 #jacquard = { path = "../../jacquard/crates/jacquard", features = ["loopback"] } 20 #jacquard-oauth = { path = "../../jacquard/crates/jacquard-oauth" } 21 #jacquard-api = { path = "../../jacquard/crates/jacquard-api", features = ["streaming"] }
+15
cli/crates/lexicons/Cargo.toml
···
··· 1 + [package] 2 + name = "wisp-lexicons" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [features] 7 + default = ["place_wisp"] 8 + place_wisp = [] 9 + 10 + [dependencies] 11 + jacquard-common = { git = "https://tangled.org/nonbinary.computer/jacquard" } 12 + jacquard-derive = { git = "https://tangled.org/nonbinary.computer/jacquard" } 13 + jacquard-lexicon = { git = "https://tangled.org/nonbinary.computer/jacquard" } 14 + serde = { version = "1.0", features = ["derive"] } 15 + rustversion = "1.0"
+1 -1
cli/src/blob_map.rs
··· 2 use jacquard_common::IntoStatic; 3 use std::collections::HashMap; 4 5 - use crate::place_wisp::fs::{Directory, EntryNode}; 6 7 /// Extract blob information from a directory tree 8 /// Returns a map of file paths to their blob refs and CIDs
··· 2 use jacquard_common::IntoStatic; 3 use std::collections::HashMap; 4 5 + use wisp_lexicons::place_wisp::fs::{Directory, EntryNode}; 6 7 /// Extract blob information from a directory tree 8 /// Returns a map of file paths to their blob refs and CIDs
cli/src/builder_types.rs cli/crates/lexicons/src/builder_types.rs
+2
cli/src/lib.rs cli/crates/lexicons/src/lib.rs
··· 1 // @generated by jacquard-lexicon. DO NOT EDIT. 2 // 3 // This file was automatically generated from Lexicon schemas.
··· 1 + extern crate alloc; 2 + 3 // @generated by jacquard-lexicon. DO NOT EDIT. 4 // 5 // This file was automatically generated from Lexicon schemas.
+13 -15
cli/src/main.rs
··· 1 - mod builder_types; 2 - mod place_wisp; 3 mod cid; 4 mod blob_map; 5 mod metadata; ··· 28 use futures::stream::{self, StreamExt}; 29 use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; 30 31 - use place_wisp::fs::*; 32 - use place_wisp::settings::*; 33 34 /// Maximum number of concurrent file uploads to the PDS 35 const MAX_CONCURRENT_UPLOADS: usize = 2; ··· 512 let chunk_file_count = subfs_utils::count_files_in_directory(chunk); 513 let chunk_size = subfs_utils::estimate_directory_size(chunk); 514 515 - let chunk_manifest = crate::place_wisp::subfs::SubfsRecord::new() 516 .root(convert_fs_dir_to_subfs_dir(chunk.clone())) 517 .file_count(Some(chunk_file_count as i64)) 518 .created_at(Datetime::now()) ··· 535 // Each chunk reference MUST have flat: true to merge chunk contents 536 println!(" → Creating parent subfs with {} chunk references...", chunk_uris.len()); 537 use jacquard_common::CowStr; 538 - use crate::place_wisp::fs::{Subfs}; 539 540 // Convert to fs::Subfs (which has the 'flat' field) instead of subfs::Subfs 541 let parent_entries_fs: Vec<Entry> = chunk_uris.iter().enumerate().map(|(i, (uri, _))| { ··· 565 let parent_tid = Tid::now_0(); 566 let parent_rkey = parent_tid.to_string(); 567 568 - let parent_manifest = crate::place_wisp::subfs::SubfsRecord::new() 569 .root(parent_root_subfs) 570 .file_count(Some(largest_dir.file_count as i64)) 571 .created_at(Datetime::now()) ··· 584 let subfs_tid = Tid::now_0(); 585 let subfs_rkey = subfs_tid.to_string(); 586 587 - let subfs_manifest = crate::place_wisp::subfs::SubfsRecord::new() 588 .root(convert_fs_dir_to_subfs_dir(largest_dir.directory.clone())) 589 .file_count(Some(largest_dir.file_count as i64)) 590 .created_at(Datetime::now()) ··· 952 953 /// Convert fs::Directory to subfs::Directory 954 /// They have the same structure, but different types 955 - fn convert_fs_dir_to_subfs_dir(fs_dir: place_wisp::fs::Directory<'static>) -> place_wisp::subfs::Directory<'static> { 956 - use place_wisp::subfs::{Directory as SubfsDirectory, Entry as SubfsEntry, EntryNode as SubfsEntryNode, File as SubfsFile}; 957 958 let subfs_entries: Vec<SubfsEntry> = fs_dir.entries.into_iter().map(|entry| { 959 let node = match entry.node { 960 - place_wisp::fs::EntryNode::File(file) => { 961 SubfsEntryNode::File(Box::new(SubfsFile::new() 962 .r#type(file.r#type) 963 .blob(file.blob) ··· 966 .base64(file.base64) 967 .build())) 968 } 969 - place_wisp::fs::EntryNode::Directory(dir) => { 970 SubfsEntryNode::Directory(Box::new(convert_fs_dir_to_subfs_dir(*dir))) 971 } 972 - place_wisp::fs::EntryNode::Subfs(subfs) => { 973 // Nested subfs in the directory we're converting 974 // Note: subfs::Subfs doesn't have the 'flat' field - that's only in fs::Subfs 975 - SubfsEntryNode::Subfs(Box::new(place_wisp::subfs::Subfs::new() 976 .r#type(subfs.r#type) 977 .subject(subfs.subject) 978 .build())) 979 } 980 - place_wisp::fs::EntryNode::Unknown(unknown) => { 981 SubfsEntryNode::Unknown(unknown) 982 } 983 };
··· 1 mod cid; 2 mod blob_map; 3 mod metadata; ··· 26 use futures::stream::{self, StreamExt}; 27 use indicatif::{ProgressBar, ProgressStyle, MultiProgress}; 28 29 + use wisp_lexicons::place_wisp::fs::*; 30 + use wisp_lexicons::place_wisp::settings::*; 31 32 /// Maximum number of concurrent file uploads to the PDS 33 const MAX_CONCURRENT_UPLOADS: usize = 2; ··· 510 let chunk_file_count = subfs_utils::count_files_in_directory(chunk); 511 let chunk_size = subfs_utils::estimate_directory_size(chunk); 512 513 + let chunk_manifest = wisp_lexicons::place_wisp::subfs::SubfsRecord::new() 514 .root(convert_fs_dir_to_subfs_dir(chunk.clone())) 515 .file_count(Some(chunk_file_count as i64)) 516 .created_at(Datetime::now()) ··· 533 // Each chunk reference MUST have flat: true to merge chunk contents 534 println!(" → Creating parent subfs with {} chunk references...", chunk_uris.len()); 535 use jacquard_common::CowStr; 536 + use wisp_lexicons::place_wisp::fs::{Subfs}; 537 538 // Convert to fs::Subfs (which has the 'flat' field) instead of subfs::Subfs 539 let parent_entries_fs: Vec<Entry> = chunk_uris.iter().enumerate().map(|(i, (uri, _))| { ··· 563 let parent_tid = Tid::now_0(); 564 let parent_rkey = parent_tid.to_string(); 565 566 + let parent_manifest = wisp_lexicons::place_wisp::subfs::SubfsRecord::new() 567 .root(parent_root_subfs) 568 .file_count(Some(largest_dir.file_count as i64)) 569 .created_at(Datetime::now()) ··· 582 let subfs_tid = Tid::now_0(); 583 let subfs_rkey = subfs_tid.to_string(); 584 585 + let subfs_manifest = wisp_lexicons::place_wisp::subfs::SubfsRecord::new() 586 .root(convert_fs_dir_to_subfs_dir(largest_dir.directory.clone())) 587 .file_count(Some(largest_dir.file_count as i64)) 588 .created_at(Datetime::now()) ··· 950 951 /// Convert fs::Directory to subfs::Directory 952 /// They have the same structure, but different types 953 + fn convert_fs_dir_to_subfs_dir(fs_dir: wisp_lexicons::place_wisp::fs::Directory<'static>) -> wisp_lexicons::place_wisp::subfs::Directory<'static> { 954 + use wisp_lexicons::place_wisp::subfs::{Directory as SubfsDirectory, Entry as SubfsEntry, EntryNode as SubfsEntryNode, File as SubfsFile}; 955 956 let subfs_entries: Vec<SubfsEntry> = fs_dir.entries.into_iter().map(|entry| { 957 let node = match entry.node { 958 + wisp_lexicons::place_wisp::fs::EntryNode::File(file) => { 959 SubfsEntryNode::File(Box::new(SubfsFile::new() 960 .r#type(file.r#type) 961 .blob(file.blob) ··· 964 .base64(file.base64) 965 .build())) 966 } 967 + wisp_lexicons::place_wisp::fs::EntryNode::Directory(dir) => { 968 SubfsEntryNode::Directory(Box::new(convert_fs_dir_to_subfs_dir(*dir))) 969 } 970 + wisp_lexicons::place_wisp::fs::EntryNode::Subfs(subfs) => { 971 // Nested subfs in the directory we're converting 972 // Note: subfs::Subfs doesn't have the 'flat' field - that's only in fs::Subfs 973 + SubfsEntryNode::Subfs(Box::new(wisp_lexicons::place_wisp::subfs::Subfs::new() 974 .r#type(subfs.r#type) 975 .subject(subfs.subject) 976 .build())) 977 } 978 + wisp_lexicons::place_wisp::fs::EntryNode::Unknown(unknown) => { 979 SubfsEntryNode::Unknown(unknown) 980 } 981 };
-9
cli/src/mod.rs
··· 1 - // @generated by jacquard-lexicon. DO NOT EDIT. 2 - // 3 - // This file was automatically generated from Lexicon schemas. 4 - // Any manual changes will be overwritten on the next regeneration. 5 - 6 - pub mod builder_types; 7 - 8 - #[cfg(feature = "place_wisp")] 9 - pub mod place_wisp;
···
cli/src/place_wisp.rs cli/crates/lexicons/src/place_wisp.rs
+34 -34
cli/src/place_wisp/fs.rs cli/crates/lexicons/src/place_wisp/fs.rs
··· 554 } 555 /// State trait tracking which required fields have been set 556 pub trait State: sealed::Sealed { 557 - type Name; 558 type Node; 559 } 560 /// Empty state - all required fields are unset 561 pub struct Empty(()); 562 impl sealed::Sealed for Empty {} 563 impl State for Empty { 564 - type Name = Unset; 565 type Node = Unset; 566 - } 567 - ///State transition - sets the `name` field to Set 568 - pub struct SetName<S: State = Empty>(PhantomData<fn() -> S>); 569 - impl<S: State> sealed::Sealed for SetName<S> {} 570 - impl<S: State> State for SetName<S> { 571 - type Name = Set<members::name>; 572 - type Node = S::Node; 573 } 574 ///State transition - sets the `node` field to Set 575 pub struct SetNode<S: State = Empty>(PhantomData<fn() -> S>); 576 impl<S: State> sealed::Sealed for SetNode<S> {} 577 impl<S: State> State for SetNode<S> { 578 - type Name = S::Name; 579 type Node = Set<members::node>; 580 } 581 /// Marker types for field names 582 #[allow(non_camel_case_types)] 583 pub mod members { 584 ///Marker type for the `name` field 585 pub struct name(()); 586 - ///Marker type for the `node` field 587 - pub struct node(()); 588 } 589 } 590 ··· 657 impl<'a, S> EntryBuilder<'a, S> 658 where 659 S: entry_state::State, 660 - S::Name: entry_state::IsSet, 661 S::Node: entry_state::IsSet, 662 { 663 /// Build the final struct 664 pub fn build(self) -> Entry<'a> { ··· 749 pub struct File<'a> { 750 /// True if blob content is base64-encoded (used to bypass PDS content sniffing) 751 #[serde(skip_serializing_if = "std::option::Option::is_none")] 752 - pub base64: Option<bool>, 753 /// Content blob ref 754 #[serde(borrow)] 755 pub blob: jacquard_common::types::blob::BlobRef<'a>, 756 /// Content encoding (e.g., gzip for compressed files) 757 #[serde(skip_serializing_if = "std::option::Option::is_none")] 758 #[serde(borrow)] 759 - pub encoding: Option<jacquard_common::CowStr<'a>>, 760 /// Original MIME type before compression 761 #[serde(skip_serializing_if = "std::option::Option::is_none")] 762 #[serde(borrow)] 763 - pub mime_type: Option<jacquard_common::CowStr<'a>>, 764 #[serde(borrow)] 765 pub r#type: jacquard_common::CowStr<'a>, 766 } ··· 994 pub struct Fs<'a> { 995 pub created_at: jacquard_common::types::string::Datetime, 996 #[serde(skip_serializing_if = "std::option::Option::is_none")] 997 - pub file_count: Option<i64>, 998 #[serde(borrow)] 999 pub root: crate::place_wisp::fs::Directory<'a>, 1000 #[serde(borrow)] ··· 1011 } 1012 /// State trait tracking which required fields have been set 1013 pub trait State: sealed::Sealed { 1014 type Site; 1015 type Root; 1016 - type CreatedAt; 1017 } 1018 /// Empty state - all required fields are unset 1019 pub struct Empty(()); 1020 impl sealed::Sealed for Empty {} 1021 impl State for Empty { 1022 type Site = Unset; 1023 type Root = Unset; 1024 - type CreatedAt = Unset; 1025 } 1026 ///State transition - sets the `site` field to Set 1027 pub struct SetSite<S: State = Empty>(PhantomData<fn() -> S>); 1028 impl<S: State> sealed::Sealed for SetSite<S> {} 1029 impl<S: State> State for SetSite<S> { 1030 type Site = Set<members::site>; 1031 type Root = S::Root; 1032 - type CreatedAt = S::CreatedAt; 1033 } 1034 ///State transition - sets the `root` field to Set 1035 pub struct SetRoot<S: State = Empty>(PhantomData<fn() -> S>); 1036 impl<S: State> sealed::Sealed for SetRoot<S> {} 1037 impl<S: State> State for SetRoot<S> { 1038 - type Site = S::Site; 1039 - type Root = Set<members::root>; 1040 type CreatedAt = S::CreatedAt; 1041 - } 1042 - ///State transition - sets the `created_at` field to Set 1043 - pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>); 1044 - impl<S: State> sealed::Sealed for SetCreatedAt<S> {} 1045 - impl<S: State> State for SetCreatedAt<S> { 1046 type Site = S::Site; 1047 - type Root = S::Root; 1048 - type CreatedAt = Set<members::created_at>; 1049 } 1050 /// Marker types for field names 1051 #[allow(non_camel_case_types)] 1052 pub mod members { 1053 ///Marker type for the `site` field 1054 pub struct site(()); 1055 ///Marker type for the `root` field 1056 pub struct root(()); 1057 - ///Marker type for the `created_at` field 1058 - pub struct created_at(()); 1059 } 1060 } 1061 ··· 1162 impl<'a, S> FsBuilder<'a, S> 1163 where 1164 S: fs_state::State, 1165 S::Site: fs_state::IsSet, 1166 S::Root: fs_state::IsSet, 1167 - S::CreatedAt: fs_state::IsSet, 1168 { 1169 /// Build the final struct 1170 pub fn build(self) -> Fs<'a> { ··· 1306 )] 1307 #[serde(rename_all = "camelCase")] 1308 pub struct Subfs<'a> { 1309 - /// If true, the subfs record's root entries are merged (flattened) into the parent directory, replacing the subfs entry. If false (default), the subfs entries are placed in a subdirectory with the subfs entry's name. Flat merging is useful for splitting large directories across multiple records while maintaining a flat structure. 1310 #[serde(skip_serializing_if = "std::option::Option::is_none")] 1311 - pub flat: Option<bool>, 1312 /// AT-URI pointing to a place.wisp.subfs record containing this subtree. 1313 #[serde(borrow)] 1314 pub subject: jacquard_common::types::string::AtUri<'a>,
··· 554 } 555 /// State trait tracking which required fields have been set 556 pub trait State: sealed::Sealed { 557 type Node; 558 + type Name; 559 } 560 /// Empty state - all required fields are unset 561 pub struct Empty(()); 562 impl sealed::Sealed for Empty {} 563 impl State for Empty { 564 type Node = Unset; 565 + type Name = Unset; 566 } 567 ///State transition - sets the `node` field to Set 568 pub struct SetNode<S: State = Empty>(PhantomData<fn() -> S>); 569 impl<S: State> sealed::Sealed for SetNode<S> {} 570 impl<S: State> State for SetNode<S> { 571 type Node = Set<members::node>; 572 + type Name = S::Name; 573 + } 574 + ///State transition - sets the `name` field to Set 575 + pub struct SetName<S: State = Empty>(PhantomData<fn() -> S>); 576 + impl<S: State> sealed::Sealed for SetName<S> {} 577 + impl<S: State> State for SetName<S> { 578 + type Node = S::Node; 579 + type Name = Set<members::name>; 580 } 581 /// Marker types for field names 582 #[allow(non_camel_case_types)] 583 pub mod members { 584 + ///Marker type for the `node` field 585 + pub struct node(()); 586 ///Marker type for the `name` field 587 pub struct name(()); 588 } 589 } 590 ··· 657 impl<'a, S> EntryBuilder<'a, S> 658 where 659 S: entry_state::State, 660 S::Node: entry_state::IsSet, 661 + S::Name: entry_state::IsSet, 662 { 663 /// Build the final struct 664 pub fn build(self) -> Entry<'a> { ··· 749 pub struct File<'a> { 750 /// True if blob content is base64-encoded (used to bypass PDS content sniffing) 751 #[serde(skip_serializing_if = "std::option::Option::is_none")] 752 + pub base64: std::option::Option<bool>, 753 /// Content blob ref 754 #[serde(borrow)] 755 pub blob: jacquard_common::types::blob::BlobRef<'a>, 756 /// Content encoding (e.g., gzip for compressed files) 757 #[serde(skip_serializing_if = "std::option::Option::is_none")] 758 #[serde(borrow)] 759 + pub encoding: std::option::Option<jacquard_common::CowStr<'a>>, 760 /// Original MIME type before compression 761 #[serde(skip_serializing_if = "std::option::Option::is_none")] 762 #[serde(borrow)] 763 + pub mime_type: std::option::Option<jacquard_common::CowStr<'a>>, 764 #[serde(borrow)] 765 pub r#type: jacquard_common::CowStr<'a>, 766 } ··· 994 pub struct Fs<'a> { 995 pub created_at: jacquard_common::types::string::Datetime, 996 #[serde(skip_serializing_if = "std::option::Option::is_none")] 997 + pub file_count: std::option::Option<i64>, 998 #[serde(borrow)] 999 pub root: crate::place_wisp::fs::Directory<'a>, 1000 #[serde(borrow)] ··· 1011 } 1012 /// State trait tracking which required fields have been set 1013 pub trait State: sealed::Sealed { 1014 + type CreatedAt; 1015 type Site; 1016 type Root; 1017 } 1018 /// Empty state - all required fields are unset 1019 pub struct Empty(()); 1020 impl sealed::Sealed for Empty {} 1021 impl State for Empty { 1022 + type CreatedAt = Unset; 1023 type Site = Unset; 1024 type Root = Unset; 1025 + } 1026 + ///State transition - sets the `created_at` field to Set 1027 + pub struct SetCreatedAt<S: State = Empty>(PhantomData<fn() -> S>); 1028 + impl<S: State> sealed::Sealed for SetCreatedAt<S> {} 1029 + impl<S: State> State for SetCreatedAt<S> { 1030 + type CreatedAt = Set<members::created_at>; 1031 + type Site = S::Site; 1032 + type Root = S::Root; 1033 } 1034 ///State transition - sets the `site` field to Set 1035 pub struct SetSite<S: State = Empty>(PhantomData<fn() -> S>); 1036 impl<S: State> sealed::Sealed for SetSite<S> {} 1037 impl<S: State> State for SetSite<S> { 1038 + type CreatedAt = S::CreatedAt; 1039 type Site = Set<members::site>; 1040 type Root = S::Root; 1041 } 1042 ///State transition - sets the `root` field to Set 1043 pub struct SetRoot<S: State = Empty>(PhantomData<fn() -> S>); 1044 impl<S: State> sealed::Sealed for SetRoot<S> {} 1045 impl<S: State> State for SetRoot<S> { 1046 type CreatedAt = S::CreatedAt; 1047 type Site = S::Site; 1048 + type Root = Set<members::root>; 1049 } 1050 /// Marker types for field names 1051 #[allow(non_camel_case_types)] 1052 pub mod members { 1053 + ///Marker type for the `created_at` field 1054 + pub struct created_at(()); 1055 ///Marker type for the `site` field 1056 pub struct site(()); 1057 ///Marker type for the `root` field 1058 pub struct root(()); 1059 } 1060 } 1061 ··· 1162 impl<'a, S> FsBuilder<'a, S> 1163 where 1164 S: fs_state::State, 1165 + S::CreatedAt: fs_state::IsSet, 1166 S::Site: fs_state::IsSet, 1167 S::Root: fs_state::IsSet, 1168 { 1169 /// Build the final struct 1170 pub fn build(self) -> Fs<'a> { ··· 1306 )] 1307 #[serde(rename_all = "camelCase")] 1308 pub struct Subfs<'a> { 1309 + /// If true (default), the subfs record's root entries are merged (flattened) into the parent directory, replacing the subfs entry. If false, the subfs entries are placed in a subdirectory with the subfs entry's name. Flat merging is useful for splitting large directories across multiple records while maintaining a flat structure. 1310 #[serde(skip_serializing_if = "std::option::Option::is_none")] 1311 + pub flat: std::option::Option<bool>, 1312 /// AT-URI pointing to a place.wisp.subfs record containing this subtree. 1313 #[serde(borrow)] 1314 pub subject: jacquard_common::types::string::AtUri<'a>,
cli/src/place_wisp/settings.rs cli/crates/lexicons/src/place_wisp/settings.rs
+30 -30
cli/src/place_wisp/subfs.rs cli/crates/lexicons/src/place_wisp/subfs.rs
··· 725 pub struct File<'a> { 726 /// True if blob content is base64-encoded (used to bypass PDS content sniffing) 727 #[serde(skip_serializing_if = "std::option::Option::is_none")] 728 - pub base64: Option<bool>, 729 /// Content blob ref 730 #[serde(borrow)] 731 pub blob: jacquard_common::types::blob::BlobRef<'a>, 732 /// Content encoding (e.g., gzip for compressed files) 733 #[serde(skip_serializing_if = "std::option::Option::is_none")] 734 #[serde(borrow)] 735 - pub encoding: Option<jacquard_common::CowStr<'a>>, 736 /// Original MIME type before compression 737 #[serde(skip_serializing_if = "std::option::Option::is_none")] 738 #[serde(borrow)] 739 - pub mime_type: Option<jacquard_common::CowStr<'a>>, 740 #[serde(borrow)] 741 pub r#type: jacquard_common::CowStr<'a>, 742 } ··· 751 } 752 /// State trait tracking which required fields have been set 753 pub trait State: sealed::Sealed { 754 - type Type; 755 type Blob; 756 } 757 /// Empty state - all required fields are unset 758 pub struct Empty(()); 759 impl sealed::Sealed for Empty {} 760 impl State for Empty { 761 - type Type = Unset; 762 type Blob = Unset; 763 - } 764 - ///State transition - sets the `type` field to Set 765 - pub struct SetType<S: State = Empty>(PhantomData<fn() -> S>); 766 - impl<S: State> sealed::Sealed for SetType<S> {} 767 - impl<S: State> State for SetType<S> { 768 - type Type = Set<members::r#type>; 769 - type Blob = S::Blob; 770 } 771 ///State transition - sets the `blob` field to Set 772 pub struct SetBlob<S: State = Empty>(PhantomData<fn() -> S>); 773 impl<S: State> sealed::Sealed for SetBlob<S> {} 774 impl<S: State> State for SetBlob<S> { 775 type Type = S::Type; 776 - type Blob = Set<members::blob>; 777 } 778 /// Marker types for field names 779 #[allow(non_camel_case_types)] 780 pub mod members { 781 ///Marker type for the `type` field 782 pub struct r#type(()); 783 - ///Marker type for the `blob` field 784 - pub struct blob(()); 785 } 786 } 787 ··· 905 impl<'a, S> FileBuilder<'a, S> 906 where 907 S: file_state::State, 908 - S::Type: file_state::IsSet, 909 S::Blob: file_state::IsSet, 910 { 911 /// Build the final struct 912 pub fn build(self) -> File<'a> { ··· 970 pub struct SubfsRecord<'a> { 971 pub created_at: jacquard_common::types::string::Datetime, 972 #[serde(skip_serializing_if = "std::option::Option::is_none")] 973 - pub file_count: Option<i64>, 974 #[serde(borrow)] 975 pub root: crate::place_wisp::subfs::Directory<'a>, 976 } ··· 1260 } 1261 /// State trait tracking which required fields have been set 1262 pub trait State: sealed::Sealed { 1263 - type Type; 1264 type Subject; 1265 } 1266 /// Empty state - all required fields are unset 1267 pub struct Empty(()); 1268 impl sealed::Sealed for Empty {} 1269 impl State for Empty { 1270 - type Type = Unset; 1271 type Subject = Unset; 1272 - } 1273 - ///State transition - sets the `type` field to Set 1274 - pub struct SetType<S: State = Empty>(PhantomData<fn() -> S>); 1275 - impl<S: State> sealed::Sealed for SetType<S> {} 1276 - impl<S: State> State for SetType<S> { 1277 - type Type = Set<members::r#type>; 1278 - type Subject = S::Subject; 1279 } 1280 ///State transition - sets the `subject` field to Set 1281 pub struct SetSubject<S: State = Empty>(PhantomData<fn() -> S>); 1282 impl<S: State> sealed::Sealed for SetSubject<S> {} 1283 impl<S: State> State for SetSubject<S> { 1284 - type Type = S::Type; 1285 type Subject = Set<members::subject>; 1286 } 1287 /// Marker types for field names 1288 #[allow(non_camel_case_types)] 1289 pub mod members { 1290 - ///Marker type for the `type` field 1291 - pub struct r#type(()); 1292 ///Marker type for the `subject` field 1293 pub struct subject(()); 1294 } 1295 } 1296 ··· 1363 impl<'a, S> SubfsBuilder<'a, S> 1364 where 1365 S: subfs_state::State, 1366 - S::Type: subfs_state::IsSet, 1367 S::Subject: subfs_state::IsSet, 1368 { 1369 /// Build the final struct 1370 pub fn build(self) -> Subfs<'a> {
··· 725 pub struct File<'a> { 726 /// True if blob content is base64-encoded (used to bypass PDS content sniffing) 727 #[serde(skip_serializing_if = "std::option::Option::is_none")] 728 + pub base64: std::option::Option<bool>, 729 /// Content blob ref 730 #[serde(borrow)] 731 pub blob: jacquard_common::types::blob::BlobRef<'a>, 732 /// Content encoding (e.g., gzip for compressed files) 733 #[serde(skip_serializing_if = "std::option::Option::is_none")] 734 #[serde(borrow)] 735 + pub encoding: std::option::Option<jacquard_common::CowStr<'a>>, 736 /// Original MIME type before compression 737 #[serde(skip_serializing_if = "std::option::Option::is_none")] 738 #[serde(borrow)] 739 + pub mime_type: std::option::Option<jacquard_common::CowStr<'a>>, 740 #[serde(borrow)] 741 pub r#type: jacquard_common::CowStr<'a>, 742 } ··· 751 } 752 /// State trait tracking which required fields have been set 753 pub trait State: sealed::Sealed { 754 type Blob; 755 + type Type; 756 } 757 /// Empty state - all required fields are unset 758 pub struct Empty(()); 759 impl sealed::Sealed for Empty {} 760 impl State for Empty { 761 type Blob = Unset; 762 + type Type = Unset; 763 } 764 ///State transition - sets the `blob` field to Set 765 pub struct SetBlob<S: State = Empty>(PhantomData<fn() -> S>); 766 impl<S: State> sealed::Sealed for SetBlob<S> {} 767 impl<S: State> State for SetBlob<S> { 768 + type Blob = Set<members::blob>; 769 type Type = S::Type; 770 + } 771 + ///State transition - sets the `type` field to Set 772 + pub struct SetType<S: State = Empty>(PhantomData<fn() -> S>); 773 + impl<S: State> sealed::Sealed for SetType<S> {} 774 + impl<S: State> State for SetType<S> { 775 + type Blob = S::Blob; 776 + type Type = Set<members::r#type>; 777 } 778 /// Marker types for field names 779 #[allow(non_camel_case_types)] 780 pub mod members { 781 + ///Marker type for the `blob` field 782 + pub struct blob(()); 783 ///Marker type for the `type` field 784 pub struct r#type(()); 785 } 786 } 787 ··· 905 impl<'a, S> FileBuilder<'a, S> 906 where 907 S: file_state::State, 908 S::Blob: file_state::IsSet, 909 + S::Type: file_state::IsSet, 910 { 911 /// Build the final struct 912 pub fn build(self) -> File<'a> { ··· 970 pub struct SubfsRecord<'a> { 971 pub created_at: jacquard_common::types::string::Datetime, 972 #[serde(skip_serializing_if = "std::option::Option::is_none")] 973 + pub file_count: std::option::Option<i64>, 974 #[serde(borrow)] 975 pub root: crate::place_wisp::subfs::Directory<'a>, 976 } ··· 1260 } 1261 /// State trait tracking which required fields have been set 1262 pub trait State: sealed::Sealed { 1263 type Subject; 1264 + type Type; 1265 } 1266 /// Empty state - all required fields are unset 1267 pub struct Empty(()); 1268 impl sealed::Sealed for Empty {} 1269 impl State for Empty { 1270 type Subject = Unset; 1271 + type Type = Unset; 1272 } 1273 ///State transition - sets the `subject` field to Set 1274 pub struct SetSubject<S: State = Empty>(PhantomData<fn() -> S>); 1275 impl<S: State> sealed::Sealed for SetSubject<S> {} 1276 impl<S: State> State for SetSubject<S> { 1277 type Subject = Set<members::subject>; 1278 + type Type = S::Type; 1279 + } 1280 + ///State transition - sets the `type` field to Set 1281 + pub struct SetType<S: State = Empty>(PhantomData<fn() -> S>); 1282 + impl<S: State> sealed::Sealed for SetType<S> {} 1283 + impl<S: State> State for SetType<S> { 1284 + type Subject = S::Subject; 1285 + type Type = Set<members::r#type>; 1286 } 1287 /// Marker types for field names 1288 #[allow(non_camel_case_types)] 1289 pub mod members { 1290 ///Marker type for the `subject` field 1291 pub struct subject(()); 1292 + ///Marker type for the `type` field 1293 + pub struct r#type(()); 1294 } 1295 } 1296 ··· 1363 impl<'a, S> SubfsBuilder<'a, S> 1364 where 1365 S: subfs_state::State, 1366 S::Subject: subfs_state::IsSet, 1367 + S::Type: subfs_state::IsSet, 1368 { 1369 /// Build the final struct 1370 pub fn build(self) -> Subfs<'a> {
+12 -12
cli/src/pull.rs
··· 1 use crate::blob_map; 2 use crate::download; 3 use crate::metadata::SiteMetadata; 4 - use crate::place_wisp::fs::*; 5 use crate::subfs_utils; 6 use jacquard::CowStr; 7 use jacquard::prelude::IdentityResolver; ··· 410 ) -> miette::Result<Directory<'static>> { 411 use jacquard_common::IntoStatic; 412 use jacquard_common::types::value::from_data; 413 - use crate::place_wisp::subfs::SubfsRecord; 414 415 - let mut all_subfs_map: HashMap<String, crate::place_wisp::subfs::Directory> = HashMap::new(); 416 let mut to_fetch = subfs_utils::extract_subfs_uris(directory, String::new()); 417 418 if to_fetch.is_empty() { ··· 516 517 /// Extract subfs URIs from a subfs::Directory (helper for pull) 518 fn extract_subfs_uris_from_subfs_dir( 519 - directory: &crate::place_wisp::subfs::Directory, 520 current_path: String, 521 ) -> Vec<(String, String)> { 522 let mut uris = Vec::new(); ··· 529 }; 530 531 match &entry.node { 532 - crate::place_wisp::subfs::EntryNode::Subfs(subfs_node) => { 533 uris.push((subfs_node.subject.to_string(), full_path.clone())); 534 } 535 - crate::place_wisp::subfs::EntryNode::Directory(subdir) => { 536 let nested = extract_subfs_uris_from_subfs_dir(subdir, full_path); 537 uris.extend(nested); 538 } ··· 546 /// Recursively replace subfs nodes with their actual content 547 fn replace_subfs_with_content( 548 directory: Directory, 549 - subfs_map: &HashMap<String, crate::place_wisp::subfs::Directory>, 550 current_path: String, 551 ) -> Directory<'static> { 552 use jacquard_common::IntoStatic; ··· 628 } 629 630 /// Convert a subfs entry to a fs entry (they have the same structure but different types) 631 - fn convert_subfs_entry_to_fs(subfs_entry: crate::place_wisp::subfs::Entry<'static>) -> Entry<'static> { 632 use jacquard_common::IntoStatic; 633 634 let node = match subfs_entry.node { 635 - crate::place_wisp::subfs::EntryNode::File(file) => { 636 EntryNode::File(Box::new( 637 File::new() 638 .r#type(file.r#type.into_static()) ··· 643 .build() 644 )) 645 } 646 - crate::place_wisp::subfs::EntryNode::Directory(dir) => { 647 let converted_entries: Vec<Entry<'static>> = dir 648 .entries 649 .into_iter() ··· 657 .build() 658 )) 659 } 660 - crate::place_wisp::subfs::EntryNode::Subfs(_nested_subfs) => { 661 // Nested subfs should have been expanded already - if we get here, it means expansion failed 662 // Treat it like a directory reference that should have been expanded 663 eprintln!(" ⚠️ Warning: unexpanded nested subfs at path, treating as empty directory"); ··· 668 .build() 669 )) 670 } 671 - crate::place_wisp::subfs::EntryNode::Unknown(unknown) => { 672 EntryNode::Unknown(unknown) 673 } 674 };
··· 1 use crate::blob_map; 2 use crate::download; 3 use crate::metadata::SiteMetadata; 4 + use wisp_lexicons::place_wisp::fs::*; 5 use crate::subfs_utils; 6 use jacquard::CowStr; 7 use jacquard::prelude::IdentityResolver; ··· 410 ) -> miette::Result<Directory<'static>> { 411 use jacquard_common::IntoStatic; 412 use jacquard_common::types::value::from_data; 413 + use wisp_lexicons::place_wisp::subfs::SubfsRecord; 414 415 + let mut all_subfs_map: HashMap<String, wisp_lexicons::place_wisp::subfs::Directory> = HashMap::new(); 416 let mut to_fetch = subfs_utils::extract_subfs_uris(directory, String::new()); 417 418 if to_fetch.is_empty() { ··· 516 517 /// Extract subfs URIs from a subfs::Directory (helper for pull) 518 fn extract_subfs_uris_from_subfs_dir( 519 + directory: &wisp_lexicons::place_wisp::subfs::Directory, 520 current_path: String, 521 ) -> Vec<(String, String)> { 522 let mut uris = Vec::new(); ··· 529 }; 530 531 match &entry.node { 532 + wisp_lexicons::place_wisp::subfs::EntryNode::Subfs(subfs_node) => { 533 uris.push((subfs_node.subject.to_string(), full_path.clone())); 534 } 535 + wisp_lexicons::place_wisp::subfs::EntryNode::Directory(subdir) => { 536 let nested = extract_subfs_uris_from_subfs_dir(subdir, full_path); 537 uris.extend(nested); 538 } ··· 546 /// Recursively replace subfs nodes with their actual content 547 fn replace_subfs_with_content( 548 directory: Directory, 549 + subfs_map: &HashMap<String, wisp_lexicons::place_wisp::subfs::Directory>, 550 current_path: String, 551 ) -> Directory<'static> { 552 use jacquard_common::IntoStatic; ··· 628 } 629 630 /// Convert a subfs entry to a fs entry (they have the same structure but different types) 631 + fn convert_subfs_entry_to_fs(subfs_entry: wisp_lexicons::place_wisp::subfs::Entry<'static>) -> Entry<'static> { 632 use jacquard_common::IntoStatic; 633 634 let node = match subfs_entry.node { 635 + wisp_lexicons::place_wisp::subfs::EntryNode::File(file) => { 636 EntryNode::File(Box::new( 637 File::new() 638 .r#type(file.r#type.into_static()) ··· 643 .build() 644 )) 645 } 646 + wisp_lexicons::place_wisp::subfs::EntryNode::Directory(dir) => { 647 let converted_entries: Vec<Entry<'static>> = dir 648 .entries 649 .into_iter() ··· 657 .build() 658 )) 659 } 660 + wisp_lexicons::place_wisp::subfs::EntryNode::Subfs(_nested_subfs) => { 661 // Nested subfs should have been expanded already - if we get here, it means expansion failed 662 // Treat it like a directory reference that should have been expanded 663 eprintln!(" ⚠️ Warning: unexpanded nested subfs at path, treating as empty directory"); ··· 668 .build() 669 )) 670 } 671 + wisp_lexicons::place_wisp::subfs::EntryNode::Unknown(unknown) => { 672 EntryNode::Unknown(unknown) 673 } 674 };
+1 -1
cli/src/serve.rs
··· 1 use crate::pull::pull_site; 2 use crate::redirects::{load_redirect_rules, match_redirect_rule, RedirectRule}; 3 - use crate::place_wisp::settings::Settings; 4 use axum::{ 5 Router, 6 extract::Request,
··· 1 use crate::pull::pull_site; 2 use crate::redirects::{load_redirect_rules, match_redirect_rule, RedirectRule}; 3 + use wisp_lexicons::place_wisp::settings::Settings; 4 use axum::{ 5 Router, 6 extract::Request,
+14 -14
cli/src/subfs_utils.rs
··· 6 use miette::IntoDiagnostic; 7 use std::collections::HashMap; 8 9 - use crate::place_wisp::fs::{Directory as FsDirectory, EntryNode as FsEntryNode}; 10 - use crate::place_wisp::subfs::SubfsRecord; 11 12 /// Extract all subfs URIs from a directory tree with their mount paths 13 pub fn extract_subfs_uris(directory: &FsDirectory, current_path: String) -> Vec<(String, String)> { ··· 145 146 /// Extract subfs URIs from a subfs::Directory 147 fn extract_subfs_uris_from_subfs_dir( 148 - directory: &crate::place_wisp::subfs::Directory, 149 current_path: String, 150 ) -> Vec<(String, String)> { 151 let mut uris = Vec::new(); 152 153 for entry in &directory.entries { 154 match &entry.node { 155 - crate::place_wisp::subfs::EntryNode::Subfs(subfs_node) => { 156 // Check if this is a chunk entry (chunk0, chunk1, etc.) 157 // Chunks should be flat-merged, so use the parent's path 158 let mount_path = if entry.name.starts_with("chunk") && ··· 171 172 uris.push((subfs_node.subject.to_string(), mount_path)); 173 } 174 - crate::place_wisp::subfs::EntryNode::Directory(subdir) => { 175 let full_path = if current_path.is_empty() { 176 entry.name.to_string() 177 } else { ··· 204 for (mount_path, subfs_record) in all_subfs { 205 // Check if this record only contains chunk subfs references (no files) 206 let only_has_chunks = subfs_record.root.entries.iter().all(|e| { 207 - matches!(&e.node, crate::place_wisp::subfs::EntryNode::Subfs(_)) && 208 e.name.starts_with("chunk") && 209 e.name.chars().skip(5).all(|c| c.is_ascii_digit()) 210 }); ··· 232 /// Extract blobs from a subfs directory (works with subfs::Directory) 233 /// Returns a map of file paths to their blob refs and CIDs 234 fn extract_subfs_blobs( 235 - directory: &crate::place_wisp::subfs::Directory, 236 current_path: String, 237 ) -> HashMap<String, (BlobRef<'static>, String)> { 238 let mut blob_map = HashMap::new(); ··· 245 }; 246 247 match &entry.node { 248 - crate::place_wisp::subfs::EntryNode::File(file_node) => { 249 let blob_ref = &file_node.blob; 250 let cid_string = blob_ref.blob().r#ref.to_string(); 251 blob_map.insert( ··· 253 (blob_ref.clone().into_static(), cid_string) 254 ); 255 } 256 - crate::place_wisp::subfs::EntryNode::Directory(subdir) => { 257 let sub_map = extract_subfs_blobs(subdir, full_path); 258 blob_map.extend(sub_map); 259 } 260 - crate::place_wisp::subfs::EntryNode::Subfs(_nested_subfs) => { 261 // Nested subfs - these should be resolved recursively in the main flow 262 // For now, we skip them (they'll be fetched separately) 263 eprintln!(" ⚠️ Found nested subfs at {}, skipping (should be fetched separately)", full_path); 264 } 265 - crate::place_wisp::subfs::EntryNode::Unknown(_) => { 266 // Skip unknown nodes 267 } 268 } ··· 352 flat: bool, 353 ) -> miette::Result<FsDirectory<'static>> { 354 use jacquard_common::CowStr; 355 - use crate::place_wisp::fs::{Entry, Subfs}; 356 357 let path_parts: Vec<&str> = target_path.split('/').collect(); 358 ··· 430 431 // Construct AT-URI and convert to RecordUri 432 let at_uri = AtUri::new(uri).into_diagnostic()?; 433 - let record_uri: RecordUri<'_, crate::place_wisp::subfs::SubfsRecordRecord> = RecordUri::try_from_uri(at_uri).into_diagnostic()?; 434 435 let rkey = record_uri.rkey() 436 .ok_or_else(|| miette::miette!("Invalid subfs URI: missing rkey"))? ··· 489 } 490 491 /// Estimate the JSON size of a single entry 492 - fn estimate_entry_size(entry: &crate::place_wisp::fs::Entry) -> usize { 493 match serde_json::to_string(entry) { 494 Ok(json) => json.len(), 495 Err(_) => 500, // Conservative estimate if serialization fails
··· 6 use miette::IntoDiagnostic; 7 use std::collections::HashMap; 8 9 + use wisp_lexicons::place_wisp::fs::{Directory as FsDirectory, EntryNode as FsEntryNode}; 10 + use wisp_lexicons::place_wisp::subfs::SubfsRecord; 11 12 /// Extract all subfs URIs from a directory tree with their mount paths 13 pub fn extract_subfs_uris(directory: &FsDirectory, current_path: String) -> Vec<(String, String)> { ··· 145 146 /// Extract subfs URIs from a subfs::Directory 147 fn extract_subfs_uris_from_subfs_dir( 148 + directory: &wisp_lexicons::place_wisp::subfs::Directory, 149 current_path: String, 150 ) -> Vec<(String, String)> { 151 let mut uris = Vec::new(); 152 153 for entry in &directory.entries { 154 match &entry.node { 155 + wisp_lexicons::place_wisp::subfs::EntryNode::Subfs(subfs_node) => { 156 // Check if this is a chunk entry (chunk0, chunk1, etc.) 157 // Chunks should be flat-merged, so use the parent's path 158 let mount_path = if entry.name.starts_with("chunk") && ··· 171 172 uris.push((subfs_node.subject.to_string(), mount_path)); 173 } 174 + wisp_lexicons::place_wisp::subfs::EntryNode::Directory(subdir) => { 175 let full_path = if current_path.is_empty() { 176 entry.name.to_string() 177 } else { ··· 204 for (mount_path, subfs_record) in all_subfs { 205 // Check if this record only contains chunk subfs references (no files) 206 let only_has_chunks = subfs_record.root.entries.iter().all(|e| { 207 + matches!(&e.node, wisp_lexicons::place_wisp::subfs::EntryNode::Subfs(_)) && 208 e.name.starts_with("chunk") && 209 e.name.chars().skip(5).all(|c| c.is_ascii_digit()) 210 }); ··· 232 /// Extract blobs from a subfs directory (works with subfs::Directory) 233 /// Returns a map of file paths to their blob refs and CIDs 234 fn extract_subfs_blobs( 235 + directory: &wisp_lexicons::place_wisp::subfs::Directory, 236 current_path: String, 237 ) -> HashMap<String, (BlobRef<'static>, String)> { 238 let mut blob_map = HashMap::new(); ··· 245 }; 246 247 match &entry.node { 248 + wisp_lexicons::place_wisp::subfs::EntryNode::File(file_node) => { 249 let blob_ref = &file_node.blob; 250 let cid_string = blob_ref.blob().r#ref.to_string(); 251 blob_map.insert( ··· 253 (blob_ref.clone().into_static(), cid_string) 254 ); 255 } 256 + wisp_lexicons::place_wisp::subfs::EntryNode::Directory(subdir) => { 257 let sub_map = extract_subfs_blobs(subdir, full_path); 258 blob_map.extend(sub_map); 259 } 260 + wisp_lexicons::place_wisp::subfs::EntryNode::Subfs(_nested_subfs) => { 261 // Nested subfs - these should be resolved recursively in the main flow 262 // For now, we skip them (they'll be fetched separately) 263 eprintln!(" ⚠️ Found nested subfs at {}, skipping (should be fetched separately)", full_path); 264 } 265 + wisp_lexicons::place_wisp::subfs::EntryNode::Unknown(_) => { 266 // Skip unknown nodes 267 } 268 } ··· 352 flat: bool, 353 ) -> miette::Result<FsDirectory<'static>> { 354 use jacquard_common::CowStr; 355 + use wisp_lexicons::place_wisp::fs::{Entry, Subfs}; 356 357 let path_parts: Vec<&str> = target_path.split('/').collect(); 358 ··· 430 431 // Construct AT-URI and convert to RecordUri 432 let at_uri = AtUri::new(uri).into_diagnostic()?; 433 + let record_uri: RecordUri<'_, wisp_lexicons::place_wisp::subfs::SubfsRecordRecord> = RecordUri::try_from_uri(at_uri).into_diagnostic()?; 434 435 let rkey = record_uri.rkey() 436 .ok_or_else(|| miette::miette!("Invalid subfs URI: missing rkey"))? ··· 489 } 490 491 /// Estimate the JSON size of a single entry 492 + fn estimate_entry_size(entry: &wisp_lexicons::place_wisp::fs::Entry) -> usize { 493 match serde_json::to_string(entry) { 494 Ok(json) => json.len(), 495 Err(_) => 500, // Conservative estimate if serialization fails
+2 -1
package.json
··· 24 "check": "cd apps/main-app && npm run check && cd ../hosting-service && npm run check", 25 "screenshot": "bun run apps/main-app/scripts/screenshot-sites.ts", 26 "hosting:dev": "cd apps/hosting-service && npm run dev", 27 - "hosting:start": "cd apps/hosting-service && npm run start" 28 }, 29 "trustedDependencies": [ 30 "@parcel/watcher",
··· 24 "check": "cd apps/main-app && npm run check && cd ../hosting-service && npm run check", 25 "screenshot": "bun run apps/main-app/scripts/screenshot-sites.ts", 26 "hosting:dev": "cd apps/hosting-service && npm run dev", 27 + "hosting:start": "cd apps/hosting-service && npm run start", 28 + "codegen": "./scripts/codegen.sh" 29 }, 30 "trustedDependencies": [ 31 "@parcel/watcher",
packages/@wisp/lexicons/lexicons/fs.json lexicons/fs.json
packages/@wisp/lexicons/lexicons/settings.json lexicons/settings.json
packages/@wisp/lexicons/lexicons/subfs.json lexicons/subfs.json
+1 -1
packages/@wisp/lexicons/package.json
··· 32 } 33 }, 34 "scripts": { 35 - "codegen": "lex gen-server ./src ./lexicons" 36 }, 37 "dependencies": { 38 "@atproto/lexicon": "^0.5.1",
··· 32 } 33 }, 34 "scripts": { 35 + "codegen": "lex gen-server ./src ../../../lexicons/*.json" 36 }, 37 "dependencies": { 38 "@atproto/lexicon": "^0.5.1",
+1 -1
packages/@wisp/lexicons/src/index.ts
··· 9 type MethodConfigOrHandler, 10 createServer as createXrpcServer, 11 } from '@atproto/xrpc-server' 12 - import { schemas } from './lexicons' 13 14 export function createServer(options?: XrpcOptions): Server { 15 return new Server(options)
··· 9 type MethodConfigOrHandler, 10 createServer as createXrpcServer, 11 } from '@atproto/xrpc-server' 12 + import { schemas } from './lexicons.js' 13 14 export function createServer(options?: XrpcOptions): Server { 15 return new Server(options)
+1 -1
packages/@wisp/lexicons/src/lexicons.ts
··· 7 ValidationError, 8 type ValidationResult, 9 } from '@atproto/lexicon' 10 - import { type $Typed, is$typed, maybe$typed } from './util' 11 12 export const schemaDict = { 13 PlaceWispFs: {
··· 7 ValidationError, 8 type ValidationResult, 9 } from '@atproto/lexicon' 10 + import { type $Typed, is$typed, maybe$typed } from './util.js' 11 12 export const schemaDict = { 13 PlaceWispFs: {
+28
scripts/codegen.sh
···
··· 1 + #!/bin/bash 2 + set -e 3 + 4 + SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 + ROOT_DIR="$(dirname "$SCRIPT_DIR")" 6 + 7 + # Parse arguments 8 + AUTO_ACCEPT="" 9 + if [[ "$1" == "-y" || "$1" == "--yes" ]]; then 10 + AUTO_ACCEPT="yes |" 11 + fi 12 + 13 + echo "=== Generating TypeScript lexicons ===" 14 + cd "$ROOT_DIR/packages/@wisp/lexicons" 15 + eval "$AUTO_ACCEPT npm run codegen" 16 + 17 + echo "=== Generating Rust lexicons ===" 18 + echo "Installing jacquard-lexgen..." 19 + cargo install jacquard-lexgen --version 0.9.5 2>/dev/null || true 20 + echo "Running jacquard-codegen..." 21 + echo " Input: $ROOT_DIR/lexicons" 22 + echo " Output: $ROOT_DIR/cli/crates/lexicons/src" 23 + jacquard-codegen -i "$ROOT_DIR/lexicons" -o "$ROOT_DIR/cli/crates/lexicons/src" 24 + 25 + # Add extern crate alloc for the macro to work 26 + sed -i '' '1s/^/extern crate alloc;\n\n/' "$ROOT_DIR/cli/crates/lexicons/src/lib.rs" 27 + 28 + echo "=== Done ==="