+94
-153
cli/Cargo.lock
+94
-153
cli/Cargo.lock
···
151
151
]
152
152
153
153
[[package]]
154
-
name = "async-lock"
155
-
version = "3.4.1"
156
-
source = "registry+https://github.com/rust-lang/crates.io-index"
157
-
checksum = "5fd03604047cee9b6ce9de9f70c6cd540a0520c813cbd49bae61f33ab80ed1dc"
158
-
dependencies = [
159
-
"event-listener",
160
-
"event-listener-strategy",
161
-
"pin-project-lite",
162
-
]
163
-
164
-
[[package]]
165
154
name = "async-trait"
166
155
version = "0.1.89"
167
156
source = "registry+https://github.com/rust-lang/crates.io-index"
···
548
537
checksum = "e47641d3deaf41fb1538ac1f54735925e275eaf3bf4d55c81b137fba797e5cbb"
549
538
550
539
[[package]]
551
-
name = "concurrent-queue"
552
-
version = "2.5.0"
553
-
source = "registry+https://github.com/rust-lang/crates.io-index"
554
-
checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
555
-
dependencies = [
556
-
"crossbeam-utils",
557
-
]
558
-
559
-
[[package]]
560
540
name = "const-oid"
561
541
version = "0.9.6"
562
542
source = "registry+https://github.com/rust-lang/crates.io-index"
···
573
553
version = "0.9.4"
574
554
source = "registry+https://github.com/rust-lang/crates.io-index"
575
555
checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f"
556
+
dependencies = [
557
+
"core-foundation-sys",
558
+
"libc",
559
+
]
560
+
561
+
[[package]]
562
+
name = "core-foundation"
563
+
version = "0.10.1"
564
+
source = "registry+https://github.com/rust-lang/crates.io-index"
565
+
checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6"
576
566
dependencies = [
577
567
"core-foundation-sys",
578
568
"libc",
···
621
611
]
622
612
623
613
[[package]]
624
-
name = "crossbeam-epoch"
625
-
version = "0.9.18"
626
-
source = "registry+https://github.com/rust-lang/crates.io-index"
627
-
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
628
-
dependencies = [
629
-
"crossbeam-utils",
630
-
]
631
-
632
-
[[package]]
633
614
name = "crossbeam-utils"
634
615
version = "0.8.21"
635
616
source = "registry+https://github.com/rust-lang/crates.io-index"
···
891
872
]
892
873
893
874
[[package]]
894
-
name = "event-listener"
895
-
version = "5.4.1"
896
-
source = "registry+https://github.com/rust-lang/crates.io-index"
897
-
checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
898
-
dependencies = [
899
-
"concurrent-queue",
900
-
"parking",
901
-
"pin-project-lite",
902
-
]
903
-
904
-
[[package]]
905
-
name = "event-listener-strategy"
906
-
version = "0.5.4"
907
-
source = "registry+https://github.com/rust-lang/crates.io-index"
908
-
checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93"
909
-
dependencies = [
910
-
"event-listener",
911
-
"pin-project-lite",
912
-
]
913
-
914
-
[[package]]
915
875
name = "fastrand"
916
876
version = "2.3.0"
917
877
source = "registry+https://github.com/rust-lang/crates.io-index"
···
996
956
]
997
957
998
958
[[package]]
959
+
name = "futures"
960
+
version = "0.3.31"
961
+
source = "registry+https://github.com/rust-lang/crates.io-index"
962
+
checksum = "65bc07b1a8bc7c85c5f2e110c476c7389b4554ba72af57d8445ea63a576b0876"
963
+
dependencies = [
964
+
"futures-channel",
965
+
"futures-core",
966
+
"futures-executor",
967
+
"futures-io",
968
+
"futures-sink",
969
+
"futures-task",
970
+
"futures-util",
971
+
]
972
+
973
+
[[package]]
999
974
name = "futures-channel"
1000
975
version = "0.3.31"
1001
976
source = "registry+https://github.com/rust-lang/crates.io-index"
1002
977
checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
1003
978
dependencies = [
1004
979
"futures-core",
980
+
"futures-sink",
1005
981
]
1006
982
1007
983
[[package]]
···
1009
985
version = "0.3.31"
1010
986
source = "registry+https://github.com/rust-lang/crates.io-index"
1011
987
checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
988
+
989
+
[[package]]
990
+
name = "futures-executor"
991
+
version = "0.3.31"
992
+
source = "registry+https://github.com/rust-lang/crates.io-index"
993
+
checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
994
+
dependencies = [
995
+
"futures-core",
996
+
"futures-task",
997
+
"futures-util",
998
+
]
1012
999
1013
1000
[[package]]
1014
1001
name = "futures-io"
···
1045
1032
source = "registry+https://github.com/rust-lang/crates.io-index"
1046
1033
checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
1047
1034
dependencies = [
1035
+
"futures-channel",
1048
1036
"futures-core",
1049
1037
"futures-io",
1050
1038
"futures-macro",
···
1253
1241
]
1254
1242
1255
1243
[[package]]
1256
-
name = "home"
1257
-
version = "0.5.12"
1258
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1259
-
checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d"
1260
-
dependencies = [
1261
-
"windows-sys 0.61.2",
1262
-
]
1263
-
1264
-
[[package]]
1265
1244
name = "html5ever"
1266
1245
version = "0.27.0"
1267
1246
source = "registry+https://github.com/rust-lang/crates.io-index"
···
1634
1613
1635
1614
[[package]]
1636
1615
name = "jacquard"
1637
-
version = "0.8.0"
1616
+
version = "0.9.0"
1638
1617
dependencies = [
1639
1618
"bytes",
1640
1619
"getrandom 0.2.16",
···
1661
1640
1662
1641
[[package]]
1663
1642
name = "jacquard-api"
1664
-
version = "0.8.0"
1643
+
version = "0.9.0"
1665
1644
dependencies = [
1666
1645
"bon",
1667
1646
"bytes",
···
1678
1657
1679
1658
[[package]]
1680
1659
name = "jacquard-common"
1681
-
version = "0.8.0"
1660
+
version = "0.9.0"
1682
1661
dependencies = [
1683
1662
"base64 0.22.1",
1684
1663
"bon",
···
1714
1693
1715
1694
[[package]]
1716
1695
name = "jacquard-derive"
1717
-
version = "0.8.0"
1696
+
version = "0.9.0"
1718
1697
dependencies = [
1719
1698
"heck 0.5.0",
1720
1699
"jacquard-lexicon",
···
1725
1704
1726
1705
[[package]]
1727
1706
name = "jacquard-identity"
1728
-
version = "0.8.0"
1707
+
version = "0.9.0"
1729
1708
dependencies = [
1730
1709
"bon",
1731
1710
"bytes",
···
1735
1714
"jacquard-common",
1736
1715
"jacquard-lexicon",
1737
1716
"miette",
1738
-
"moka",
1717
+
"mini-moka",
1739
1718
"percent-encoding",
1740
1719
"reqwest",
1741
1720
"serde",
···
1750
1729
1751
1730
[[package]]
1752
1731
name = "jacquard-lexicon"
1753
-
version = "0.8.0"
1732
+
version = "0.9.0"
1754
1733
dependencies = [
1755
1734
"cid",
1756
1735
"dashmap",
···
1775
1754
1776
1755
[[package]]
1777
1756
name = "jacquard-oauth"
1778
-
version = "0.8.0"
1757
+
version = "0.9.0"
1779
1758
dependencies = [
1780
1759
"base64 0.22.1",
1781
1760
"bytes",
···
1982
1961
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
1983
1962
1984
1963
[[package]]
1985
-
name = "malloc_buf"
1986
-
version = "0.0.6"
1987
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1988
-
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
1989
-
dependencies = [
1990
-
"libc",
1991
-
]
1992
-
1993
-
[[package]]
1994
1964
name = "markup5ever"
1995
1965
version = "0.12.1"
1996
1966
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2080
2050
]
2081
2051
2082
2052
[[package]]
2053
+
name = "mini-moka"
2054
+
version = "0.11.0"
2055
+
source = "git+https://github.com/moka-rs/mini-moka?rev=da864e849f5d034f32e02197fee9bb5d5af36d3d#da864e849f5d034f32e02197fee9bb5d5af36d3d"
2056
+
dependencies = [
2057
+
"crossbeam-channel",
2058
+
"crossbeam-utils",
2059
+
"dashmap",
2060
+
"smallvec",
2061
+
"tagptr",
2062
+
"triomphe",
2063
+
"web-time",
2064
+
]
2065
+
2066
+
[[package]]
2083
2067
name = "minimal-lexical"
2084
2068
version = "0.2.1"
2085
2069
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2107
2091
]
2108
2092
2109
2093
[[package]]
2110
-
name = "moka"
2111
-
version = "0.12.11"
2112
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2113
-
checksum = "8261cd88c312e0004c1d51baad2980c66528dfdb2bee62003e643a4d8f86b077"
2114
-
dependencies = [
2115
-
"async-lock",
2116
-
"crossbeam-channel",
2117
-
"crossbeam-epoch",
2118
-
"crossbeam-utils",
2119
-
"equivalent",
2120
-
"event-listener",
2121
-
"futures-util",
2122
-
"parking_lot",
2123
-
"portable-atomic",
2124
-
"rustc_version",
2125
-
"smallvec",
2126
-
"tagptr",
2127
-
"uuid",
2128
-
]
2129
-
2130
-
[[package]]
2131
2094
name = "multibase"
2132
2095
version = "0.9.2"
2133
2096
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2279
2242
]
2280
2243
2281
2244
[[package]]
2282
-
name = "objc"
2283
-
version = "0.2.7"
2245
+
name = "objc2"
2246
+
version = "0.6.3"
2284
2247
source = "registry+https://github.com/rust-lang/crates.io-index"
2285
-
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
2248
+
checksum = "b7c2599ce0ec54857b29ce62166b0ed9b4f6f1a70ccc9a71165b6154caca8c05"
2286
2249
dependencies = [
2287
-
"malloc_buf",
2250
+
"objc2-encode",
2251
+
]
2252
+
2253
+
[[package]]
2254
+
name = "objc2-encode"
2255
+
version = "4.1.0"
2256
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2257
+
checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33"
2258
+
2259
+
[[package]]
2260
+
name = "objc2-foundation"
2261
+
version = "0.3.2"
2262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2263
+
checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272"
2264
+
dependencies = [
2265
+
"bitflags",
2266
+
"objc2",
2288
2267
]
2289
2268
2290
2269
[[package]]
···
2411
2390
]
2412
2391
2413
2392
[[package]]
2414
-
name = "parking"
2415
-
version = "2.2.1"
2416
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2417
-
checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
2418
-
2419
-
[[package]]
2420
2393
name = "parking_lot"
2421
2394
version = "0.12.5"
2422
2395
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2530
2503
version = "0.3.32"
2531
2504
source = "registry+https://github.com/rust-lang/crates.io-index"
2532
2505
checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
2533
-
2534
-
[[package]]
2535
-
name = "portable-atomic"
2536
-
version = "1.11.1"
2537
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2538
-
checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483"
2539
2506
2540
2507
[[package]]
2541
2508
name = "potential_utf"
···
2774
2741
checksum = "d20581732dd76fa913c7dff1a2412b714afe3573e94d41c34719de73337cc8ab"
2775
2742
2776
2743
[[package]]
2777
-
name = "raw-window-handle"
2778
-
version = "0.5.2"
2779
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2780
-
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
2781
-
2782
-
[[package]]
2783
2744
name = "redox_syscall"
2784
2745
version = "0.5.18"
2785
2746
source = "registry+https://github.com/rust-lang/crates.io-index"
···
2983
2944
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
2984
2945
2985
2946
[[package]]
2986
-
name = "rustc_version"
2987
-
version = "0.4.1"
2988
-
source = "registry+https://github.com/rust-lang/crates.io-index"
2989
-
checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92"
2990
-
dependencies = [
2991
-
"semver",
2992
-
]
2993
-
2994
-
[[package]]
2995
2947
name = "rustix"
2996
2948
version = "1.1.2"
2997
2949
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3126
3078
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
3127
3079
dependencies = [
3128
3080
"bitflags",
3129
-
"core-foundation",
3081
+
"core-foundation 0.9.4",
3130
3082
"core-foundation-sys",
3131
3083
"libc",
3132
3084
"security-framework-sys",
···
3141
3093
"core-foundation-sys",
3142
3094
"libc",
3143
3095
]
3144
-
3145
-
[[package]]
3146
-
name = "semver"
3147
-
version = "1.0.27"
3148
-
source = "registry+https://github.com/rust-lang/crates.io-index"
3149
-
checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
3150
3096
3151
3097
[[package]]
3152
3098
name = "serde"
···
3540
3486
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
3541
3487
dependencies = [
3542
3488
"bitflags",
3543
-
"core-foundation",
3489
+
"core-foundation 0.9.4",
3544
3490
"system-configuration-sys",
3545
3491
]
3546
3492
···
3872
3818
]
3873
3819
3874
3820
[[package]]
3821
+
name = "triomphe"
3822
+
version = "0.1.15"
3823
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3824
+
checksum = "dd69c5aa8f924c7519d6372789a74eac5b94fb0f8fcf0d4a97eb0bfc3e785f39"
3825
+
3826
+
[[package]]
3875
3827
name = "try-lock"
3876
3828
version = "0.2.5"
3877
3829
source = "registry+https://github.com/rust-lang/crates.io-index"
···
3977
3929
checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
3978
3930
3979
3931
[[package]]
3980
-
name = "uuid"
3981
-
version = "1.18.1"
3982
-
source = "registry+https://github.com/rust-lang/crates.io-index"
3983
-
checksum = "2f87b8aa10b915a06587d0dec516c282ff295b475d94abf425d62b57710070a2"
3984
-
dependencies = [
3985
-
"getrandom 0.3.4",
3986
-
"js-sys",
3987
-
"wasm-bindgen",
3988
-
]
3989
-
3990
-
[[package]]
3991
3932
name = "vcpkg"
3992
3933
version = "0.2.15"
3993
3934
source = "registry+https://github.com/rust-lang/crates.io-index"
···
4126
4067
4127
4068
[[package]]
4128
4069
name = "webbrowser"
4129
-
version = "0.8.15"
4070
+
version = "1.0.6"
4130
4071
source = "registry+https://github.com/rust-lang/crates.io-index"
4131
-
checksum = "db67ae75a9405634f5882791678772c94ff5f16a66535aae186e26aa0841fc8b"
4072
+
checksum = "00f1243ef785213e3a32fa0396093424a3a6ea566f9948497e5a2309261a4c97"
4132
4073
dependencies = [
4133
-
"core-foundation",
4134
-
"home",
4074
+
"core-foundation 0.10.1",
4135
4075
"jni",
4136
4076
"log",
4137
4077
"ndk-context",
4138
-
"objc",
4139
-
"raw-window-handle",
4078
+
"objc2",
4079
+
"objc2-foundation",
4140
4080
"url",
4141
4081
"web-sys",
4142
4082
]
···
4577
4517
"bytes",
4578
4518
"clap",
4579
4519
"flate2",
4520
+
"futures",
4580
4521
"jacquard",
4581
4522
"jacquard-api",
4582
4523
"jacquard-common",
+1
cli/Cargo.toml
+1
cli/Cargo.toml
+95
-23
cli/src/main.rs
+95
-23
cli/src/main.rs
···
3
3
4
4
use clap::Parser;
5
5
use jacquard::CowStr;
6
-
use jacquard::client::{Agent, FileAuthStore, AgentSessionExt};
6
+
use jacquard::client::{Agent, FileAuthStore, AgentSessionExt, MemoryCredentialSession};
7
7
use jacquard::oauth::client::OAuthClient;
8
8
use jacquard::oauth::loopback::LoopbackConfig;
9
9
use jacquard::prelude::IdentityResolver;
···
15
15
use flate2::write::GzEncoder;
16
16
use std::io::Write;
17
17
use base64::Engine;
18
+
use futures::stream::{self, StreamExt};
18
19
19
20
use place_wisp::fs::*;
20
21
···
32
33
#[arg(short, long)]
33
34
site: Option<String>,
34
35
35
-
/// Path to auth store file (will be created if missing)
36
+
/// Path to auth store file (will be created if missing, only used with OAuth)
36
37
#[arg(long, default_value = "/tmp/wisp-oauth-session.json")]
37
38
store: String,
39
+
40
+
/// App Password for authentication (alternative to OAuth)
41
+
#[arg(long)]
42
+
password: Option<CowStr<'static>>,
38
43
}
39
44
40
45
#[tokio::main]
41
46
async fn main() -> miette::Result<()> {
42
47
let args = Args::parse();
43
48
44
-
let oauth = OAuthClient::with_default_config(FileAuthStore::new(&args.store));
49
+
// Dispatch to appropriate authentication method
50
+
if let Some(password) = args.password {
51
+
run_with_app_password(args.input, password, args.path, args.site).await
52
+
} else {
53
+
run_with_oauth(args.input, args.store, args.path, args.site).await
54
+
}
55
+
}
56
+
57
+
/// Run deployment with app password authentication
58
+
async fn run_with_app_password(
59
+
input: CowStr<'static>,
60
+
password: CowStr<'static>,
61
+
path: PathBuf,
62
+
site: Option<String>,
63
+
) -> miette::Result<()> {
64
+
let (session, auth) =
65
+
MemoryCredentialSession::authenticated(input, password, None).await?;
66
+
println!("Signed in as {}", auth.handle);
67
+
68
+
let agent: Agent<_> = Agent::from(session);
69
+
deploy_site(&agent, path, site).await
70
+
}
71
+
72
+
/// Run deployment with OAuth authentication
73
+
async fn run_with_oauth(
74
+
input: CowStr<'static>,
75
+
store: String,
76
+
path: PathBuf,
77
+
site: Option<String>,
78
+
) -> miette::Result<()> {
79
+
let oauth = OAuthClient::with_default_config(FileAuthStore::new(&store));
45
80
let session = oauth
46
-
.login_with_local_server(args.input, Default::default(), LoopbackConfig::default())
81
+
.login_with_local_server(input, Default::default(), LoopbackConfig::default())
47
82
.await?;
48
83
49
84
let agent: Agent<_> = Agent::from(session);
85
+
deploy_site(&agent, path, site).await
86
+
}
50
87
88
+
/// Deploy the site using the provided agent
89
+
async fn deploy_site(
90
+
agent: &Agent<impl jacquard::client::AgentSession + IdentityResolver>,
91
+
path: PathBuf,
92
+
site: Option<String>,
93
+
) -> miette::Result<()> {
51
94
// Verify the path exists
52
-
if !args.path.exists() {
53
-
return Err(miette::miette!("Path does not exist: {}", args.path.display()));
95
+
if !path.exists() {
96
+
return Err(miette::miette!("Path does not exist: {}", path.display()));
54
97
}
55
98
56
99
// Get site name
57
-
let site_name = args.site.unwrap_or_else(|| {
58
-
args.path
100
+
let site_name = site.unwrap_or_else(|| {
101
+
path
59
102
.file_name()
60
103
.and_then(|n| n.to_str())
61
104
.unwrap_or("site")
···
65
108
println!("Deploying site '{}'...", site_name);
66
109
67
110
// Build directory tree
68
-
let root_dir = build_directory(&agent, &args.path).await?;
111
+
let root_dir = build_directory(agent, &path).await?;
69
112
70
113
// Count total files
71
114
let file_count = count_files(&root_dir);
···
102
145
) -> std::pin::Pin<Box<dyn std::future::Future<Output = miette::Result<Directory<'static>>> + 'a>>
103
146
{
104
147
Box::pin(async move {
105
-
let mut entries = Vec::new();
148
+
// Collect all directory entries first
149
+
let dir_entries: Vec<_> = std::fs::read_dir(dir_path)
150
+
.into_diagnostic()?
151
+
.collect::<Result<Vec<_>, _>>()
152
+
.into_diagnostic()?;
153
+
154
+
// Separate files and directories
155
+
let mut file_tasks = Vec::new();
156
+
let mut dir_tasks = Vec::new();
106
157
107
-
for entry in std::fs::read_dir(dir_path).into_diagnostic()? {
108
-
let entry = entry.into_diagnostic()?;
158
+
for entry in dir_entries {
109
159
let path = entry.path();
110
160
let name = entry.file_name();
111
161
let name_str = name.to_str()
112
-
.ok_or_else(|| miette::miette!("Invalid filename: {:?}", name))?;
162
+
.ok_or_else(|| miette::miette!("Invalid filename: {:?}", name))?
163
+
.to_string();
113
164
114
165
// Skip hidden files
115
166
if name_str.starts_with('.') {
···
119
170
let metadata = entry.metadata().into_diagnostic()?;
120
171
121
172
if metadata.is_file() {
173
+
file_tasks.push((name_str, path));
174
+
} else if metadata.is_dir() {
175
+
dir_tasks.push((name_str, path));
176
+
}
177
+
}
178
+
179
+
// Process files concurrently with a limit of 5
180
+
let file_entries: Vec<Entry> = stream::iter(file_tasks)
181
+
.map(|(name, path)| async move {
122
182
let file_node = process_file(agent, &path).await?;
123
-
entries.push(Entry::new()
124
-
.name(CowStr::from(name_str.to_string()))
183
+
Ok::<_, miette::Report>(Entry::new()
184
+
.name(CowStr::from(name))
125
185
.node(EntryNode::File(Box::new(file_node)))
126
-
.build());
127
-
} else if metadata.is_dir() {
128
-
let subdir = build_directory(agent, &path).await?;
129
-
entries.push(Entry::new()
130
-
.name(CowStr::from(name_str.to_string()))
131
-
.node(EntryNode::Directory(Box::new(subdir)))
132
-
.build());
133
-
}
186
+
.build())
187
+
})
188
+
.buffer_unordered(5)
189
+
.collect::<Vec<_>>()
190
+
.await
191
+
.into_iter()
192
+
.collect::<miette::Result<Vec<_>>>()?;
193
+
194
+
// Process directories recursively (sequentially to avoid too much nesting)
195
+
let mut dir_entries = Vec::new();
196
+
for (name, path) in dir_tasks {
197
+
let subdir = build_directory(agent, &path).await?;
198
+
dir_entries.push(Entry::new()
199
+
.name(CowStr::from(name))
200
+
.node(EntryNode::Directory(Box::new(subdir)))
201
+
.build());
134
202
}
203
+
204
+
// Combine file and directory entries
205
+
let mut entries = file_entries;
206
+
entries.extend(dir_entries);
135
207
136
208
Ok(Directory::new()
137
209
.r#type(CowStr::from("directory"))