From ec6b15bed62a1e79c61f8b355c455fe263379dd7 Mon Sep 17 00:00:00 2001 From: Christian Date: Wed, 5 Nov 2025 15:10:39 -0600 Subject: [PATCH 1/6] fixes proxy issue by just using full url (not just path) and fixes dynamic backend generation by setting the host --- crates/anyedge-adapter-fastly/src/proxy.rs | 11 +++++++++-- examples/app-demo/crates/app-demo-core/Cargo.toml | 1 - 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/crates/anyedge-adapter-fastly/src/proxy.rs b/crates/anyedge-adapter-fastly/src/proxy.rs index 7bd1124..5c750d1 100644 --- a/crates/anyedge-adapter-fastly/src/proxy.rs +++ b/crates/anyedge-adapter-fastly/src/proxy.rs @@ -46,7 +46,7 @@ fn build_fastly_request( ) -> Result { let mut fastly_request = FastlyRequest::new( method.clone(), - uri.path_and_query().map(|pq| pq.as_str()).unwrap_or("/"), + uri.to_string(), ); fastly_request.set_method(method); @@ -103,7 +103,14 @@ fn ensure_backend(uri: &Uri) -> Result { let name = backend_name(&target, uri.scheme_str()); - match Backend::from_name(&name) { + let host_with_port = match port { + Some(p) => format!("{}:{}", host, p), + None => host.to_string(), + }; + + let builder = Backend::builder(&name, &host_with_port).override_host(host); + + match builder.finish() { Ok(backend) => Ok(backend), Err(_) => { let mut builder = Backend::builder(&name, &target); diff --git a/examples/app-demo/crates/app-demo-core/Cargo.toml b/examples/app-demo/crates/app-demo-core/Cargo.toml index a963715..d4b8081 100644 --- a/examples/app-demo/crates/app-demo-core/Cargo.toml +++ b/examples/app-demo/crates/app-demo-core/Cargo.toml @@ -15,5 +15,4 @@ futures = { workspace = true } serde = { workspace = true } [dev-dependencies] -async-trait = { workspace = true } serde_json = { workspace = true } From 910eca471157a5fdae79c41e3743e90d6dadd039 Mon Sep 17 00:00:00 2001 From: Aram Grigoryan <132480+aram356@users.noreply.github.com> Date: Thu, 6 Nov 2025 08:53:08 -0800 Subject: [PATCH 2/6] Updated Cargo.lock after modifying dependencies in Cargo.toml --- Cargo.lock | 1 - 1 file changed, 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 4f082f3..e17100f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,7 +287,6 @@ name = "app-demo-core" version = "0.1.0" dependencies = [ "anyedge-core", - "async-trait", "bytes", "futures", "serde", From 9c877fca21d9f67451e1ffe226bcf164d2197013 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 6 Nov 2025 13:36:28 -0600 Subject: [PATCH 3/6] revert removing async trait from demo app --- examples/app-demo/Cargo.lock | 980 +++++++++++++++++- .../app-demo/crates/app-demo-core/Cargo.toml | 1 + 2 files changed, 928 insertions(+), 53 deletions(-) diff --git a/examples/app-demo/Cargo.lock b/examples/app-demo/Cargo.lock index c077c4b..0dbec8a 100644 --- a/examples/app-demo/Cargo.lock +++ b/examples/app-demo/Cargo.lock @@ -50,13 +50,34 @@ dependencies = [ "libc", ] +[[package]] +name = "anyedge-adapter-axum" +version = "0.1.0" +dependencies = [ + "anyedge-core", + "anyhow", + "async-trait", + "axum 0.8.6", + "bytes", + "futures", + "futures-util", + "http", + "log", + "reqwest", + "simple_logger 5.1.0", + "thiserror 2.0.16", + "tokio", + "tower", + "tracing", +] + [[package]] name = "anyedge-adapter-cloudflare" version = "0.1.0" dependencies = [ "anyedge-core", "async-trait", - "brotli 3.5.0", + "brotli", "bytes", "flate2", "futures", @@ -73,7 +94,7 @@ dependencies = [ "anyedge-core", "async-stream", "async-trait", - "brotli 3.5.0", + "brotli", "bytes", "chrono", "fastly", @@ -83,7 +104,6 @@ dependencies = [ "futures-util", "log", "log-fastly", - "toml", ] [[package]] @@ -101,7 +121,7 @@ dependencies = [ "http", "http-body", "log", - "matchit 0.8.6", + "matchit 0.8.4", "serde", "serde_json", "serde_urlencoded", @@ -131,6 +151,21 @@ version = "1.0.99" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" +[[package]] +name = "app-demo-adapter-axum" +version = "0.1.0" +dependencies = [ + "anyedge-adapter-axum", + "anyedge-core", + "anyhow", + "app-demo-core", + "axum 0.7.9", + "log", + "simple_logger 4.3.3", + "tokio", + "tracing", +] + [[package]] name = "app-demo-adapter-cloudflare" version = "0.1.0" @@ -210,12 +245,125 @@ dependencies = [ "syn 2.0.106", ] +[[package]] +name = "atomic-waker" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" + [[package]] name = "autocfg" version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" +[[package]] +name = "axum" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" +dependencies = [ + "async-trait", + "axum-core 0.4.5", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit 0.7.3", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a18ed336352031311f4e0b4dd2ff392d4fbb370777c9d18d7fc9d7359f73871" +dependencies = [ + "axum-core 0.5.5", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-util", + "itoa", + "matchit 0.8.4", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "axum-core" +version = "0.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59446ce19cd142f8833f856eb31f3eb097812d1479ab224f54d72428ca21ea22" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "backtrace" version = "0.3.75" @@ -228,9 +376,15 @@ dependencies = [ "miniz_oxide", "object", "rustc-demangle", - "windows-targets", + "windows-targets 0.52.6", ] +[[package]] +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + [[package]] name = "bitflags" version = "1.3.2" @@ -252,17 +406,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "brotli" -version = "3.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d640d25bc63c50fb1f0b545ffd80207d2e10a4c965530809b40ba3386825c391" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor 2.5.1", -] - [[package]] name = "brotli" version = "8.0.2" @@ -271,17 +414,7 @@ checksum = "4bd8b9603c7aa97359dbd97ecf258968c95f3adddd6db2f7e7a5bef101c84560" dependencies = [ "alloc-no-stdlib", "alloc-stdlib", - "brotli-decompressor 5.0.0", -] - -[[package]] -name = "brotli-decompressor" -version = "2.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e2e4afe60d7dd600fdd3de8d0f08c2b7ec039712e3b6137ff98b7004e82de4f" -dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "brotli-decompressor", ] [[package]] @@ -322,6 +455,12 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9" +[[package]] +name = "cfg_aliases" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" + [[package]] name = "chrono" version = "0.4.42" @@ -335,13 +474,32 @@ dependencies = [ "windows-link", ] +[[package]] +name = "colored" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "117725a109d387c937a1533ce01b450cbde6b88abceea8473c4d7a85853cda3c" +dependencies = [ + "lazy_static", + "windows-sys 0.59.0", +] + +[[package]] +name = "colored" +version = "3.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "compression-codecs" version = "0.4.30" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "485abf41ac0c8047c07c87c72c8fb3eb5197f6e9d7ded615dfd1a00ae00a0f64" dependencies = [ - "brotli 8.0.2", + "brotli", "compression-core", "flate2", "memchr", @@ -533,9 +691,9 @@ dependencies = [ [[package]] name = "fern" -version = "0.6.2" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9f0c14694cbd524c8720dd69b0e3179344f04ebb5f90f2e4a440c6ea3b2f1ee" +checksum = "4316185f709b23713e41e3195f90edef7fb00c3ed4adc79769cf09cc762a3b29" dependencies = [ "log", ] @@ -670,6 +828,33 @@ dependencies = [ "version_check", ] +[[package]] +name = "getrandom" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi", + "wasip2", + "wasm-bindgen", +] + [[package]] name = "gimli" version = "0.31.1" @@ -703,6 +888,94 @@ dependencies = [ "http", ] +[[package]] +name = "http-body-util" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +dependencies = [ + "bytes", + "futures-core", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eb3aa54a13a0dfe7fbe3a59e0c76093041720fdc77b110cc0fc260fafb4dc51e" +dependencies = [ + "atomic-waker", + "bytes", + "futures-channel", + "futures-core", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "pin-utils", + "smallvec", + "tokio", + "want", +] + +[[package]] +name = "hyper-rustls" +version = "0.27.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "rustls-pki-types", + "tokio", + "tokio-rustls", + "tower-service", + "webpki-roots", +] + +[[package]] +name = "hyper-util" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c6995591a8f1380fcb4ba966a252a4b29188d51d2b89e3a252f5305be65aea8" +dependencies = [ + "base64", + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "http", + "http-body", + "hyper", + "ipnet", + "libc", + "percent-encoding", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", +] + [[package]] name = "iana-time-zone" version = "0.1.64" @@ -861,6 +1134,22 @@ dependencies = [ "libc", ] +[[package]] +name = "ipnet" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "469fb0b9cefa57e3ef31275ee7cacb78f2fdca44e4765491884a2b119d4eb130" + +[[package]] +name = "iri-string" +version = "0.7.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f867b9d1d896b67beb18518eda36fdb77a32ea590de864f1325b294a6d14397" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "itertools" version = "0.13.0" @@ -921,6 +1210,12 @@ dependencies = [ "regex", ] +[[package]] +name = "lru-slab" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154" + [[package]] name = "matchit" version = "0.7.3" @@ -929,9 +1224,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "matchit" -version = "0.8.6" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2f926ade0c4e170215ae43342bf13b9310a437609c81f29f86c5df6657582ef9" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "memchr" @@ -972,7 +1267,7 @@ checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c" dependencies = [ "libc", "wasi 0.11.1+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -990,6 +1285,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "num_threads" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c7398b9c8b70908f6371f47ed36737907c87c52af34c268fed0bf0ceb92ead9" +dependencies = [ + "libc", +] + [[package]] name = "object" version = "0.36.7" @@ -1064,6 +1368,15 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppv-lite86" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" +dependencies = [ + "zerocopy", +] + [[package]] name = "proc-macro-error-attr2" version = "2.0.0" @@ -1096,17 +1409,107 @@ dependencies = [ ] [[package]] -name = "quote" -version = "1.0.40" +name = "quinn" +version = "0.11.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +checksum = "b9e20a958963c291dc322d98411f541009df2ced7b5a4f2bd52337638cfccf20" dependencies = [ - "proc-macro2", + "bytes", + "cfg_aliases", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls", + "socket2", + "thiserror 2.0.16", + "tokio", + "tracing", + "web-time", ] [[package]] -name = "regex" -version = "1.11.2" +name = "quinn-proto" +version = "0.11.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1906b49b0c3bc04b5fe5d86a77925ae6524a19b816ae38ce1e426255f1d8a31" +dependencies = [ + "bytes", + "getrandom 0.3.4", + "lru-slab", + "rand", + "ring", + "rustc-hash", + "rustls", + "rustls-pki-types", + "slab", + "thiserror 2.0.16", + "tinyvec", + "tracing", + "web-time", +] + +[[package]] +name = "quinn-udp" +version = "0.5.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "addec6a0dcad8a8d96a771f815f0eaf55f9d1805756410b39f5fa81332574cbd" +dependencies = [ + "cfg_aliases", + "libc", + "once_cell", + "socket2", + "tracing", + "windows-sys 0.59.0", +] + +[[package]] +name = "quote" +version = "1.0.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "r-efi" +version = "5.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" + +[[package]] +name = "rand" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1" +dependencies = [ + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" +dependencies = [ + "getrandom 0.3.4", +] + +[[package]] +name = "regex" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912" dependencies = [ @@ -1133,12 +1536,105 @@ version = "0.8.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001" +[[package]] +name = "reqwest" +version = "0.12.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d0946410b9f7b082a427e4ef5c8ff541a88b357bc6c637c40db3a68ac70a36f" +dependencies = [ + "base64", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "webpki-roots", +] + +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.16", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + [[package]] name = "rustc-demangle" version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace" +[[package]] +name = "rustc-hash" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d" + +[[package]] +name = "rustls" +version = "0.23.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "533f54bc6a7d4f647e46ad909549eda97bf5afc1585190ef692b4286b198bd8f" +dependencies = [ + "once_cell", + "ring", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-pki-types" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94182ad936a0c91c324cd46c6511b9510ed16af436d7b5bab34beab0afd55f7a" +dependencies = [ + "web-time", + "zeroize", +] + +[[package]] +name = "rustls-webpki" +version = "0.103.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ffdfa2f5286e2247234e03f680868ac2815974dc39e00ea15adc445d0aafe52" +dependencies = [ + "ring", + "rustls-pki-types", + "untrusted", +] + [[package]] name = "rustversion" version = "1.0.22" @@ -1214,6 +1710,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "serde_path_to_error" +version = "0.1.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" +dependencies = [ + "itoa", + "serde", + "serde_core", +] + [[package]] name = "serde_repr" version = "0.1.20" @@ -1265,6 +1772,39 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b" +dependencies = [ + "libc", +] + +[[package]] +name = "simple_logger" +version = "4.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e7e46c8c90251d47d08b28b8a419ffb4aede0f87c2eea95e17d1d5bacbf3ef1" +dependencies = [ + "colored 2.2.0", + "log", + "time", + "windows-sys 0.48.0", +] + +[[package]] +name = "simple_logger" +version = "5.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291bee647ce7310b0ea721bfd7e0525517b4468eb7c7e15eb8bd774343179702" +dependencies = [ + "colored 3.0.0", + "log", + "time", + "windows-sys 0.61.2", +] + [[package]] name = "slab" version = "0.4.11" @@ -1277,6 +1817,16 @@ version = "1.15.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" +[[package]] +name = "socket2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17129e116933cf371d018bb80ae557e889637989d8638274fb25622827b03881" +dependencies = [ + "libc", + "windows-sys 0.60.2", +] + [[package]] name = "stable_deref_trait" version = "1.2.0" @@ -1289,6 +1839,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" version = "1.0.109" @@ -1311,6 +1867,15 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" +dependencies = [ + "futures-core", +] + [[package]] name = "synstructure" version = "0.13.2" @@ -1364,12 +1929,15 @@ dependencies = [ [[package]] name = "time" -version = "0.3.43" +version = "0.3.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83bde6f1ec10e72d583d91623c939f623002284ef622b87de38cfd546cbf2031" +checksum = "91e7d9e3bb61134e77bde20dd4825b97c010155709965fedf0f49bb138e52a9d" dependencies = [ "deranged", + "itoa", + "libc", "num-conv", + "num_threads", "powerfmt", "serde", "time-core", @@ -1402,6 +1970,21 @@ dependencies = [ "zerovec", ] +[[package]] +name = "tinyvec" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "tokio" version = "1.47.1" @@ -1409,11 +1992,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038" dependencies = [ "backtrace", + "bytes", "io-uring", "libc", "mio", "pin-project-lite", + "signal-hook-registry", "slab", + "socket2", + "tokio-macros", + "windows-sys 0.59.0", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1729aa945f29d91ba541258c8df89027d5792d85a8841fb65e8bf0f4ede4ef61" +dependencies = [ + "rustls", + "tokio", ] [[package]] @@ -1455,6 +2064,46 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d163a63c116ce562a22cda521fcc4d79152e7aba014456fb5eb442f6d6a10109" +[[package]] +name = "tower" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d039ad9159c98b70ecfd540b2573b97f7f52c3e8d9f8ad57a24b916a536975f9" +dependencies = [ + "futures-core", + "futures-util", + "pin-project-lite", + "sync_wrapper", + "tokio", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-http" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2" +dependencies = [ + "bitflags 2.9.4", + "bytes", + "futures-util", + "http", + "http-body", + "iri-string", + "pin-project-lite", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "tower-layer" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" + [[package]] name = "tower-service" version = "0.3.3" @@ -1467,6 +2116,7 @@ version = "0.1.41" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0" dependencies = [ + "log", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1492,6 +2142,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.18.0" @@ -1504,6 +2160,12 @@ version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f63a545481291138910575129486daeaf8ac54aee4387fe7906919f7830c7d9d" +[[package]] +name = "untrusted" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" + [[package]] name = "url" version = "2.5.7" @@ -1568,6 +2230,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -1711,13 +2382,32 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "web-time" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki-roots" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2878ef029c47c6e8cf779119f20fcf52bde7ad42a731b2a304bc221df17571e" +dependencies = [ + "rustls-pki-types", +] + [[package]] name = "winapi-util" version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys", + "windows-sys 0.59.0", ] [[package]] @@ -1757,9 +2447,9 @@ dependencies = [ [[package]] name = "windows-link" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45e46c0661abb7180e7b9c281db115305d49ca1709ab8242adf09666d2173c65" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] name = "windows-result" @@ -1779,13 +2469,64 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-sys" version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" dependencies = [ - "windows-targets", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-sys" +version = "0.60.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" +dependencies = [ + "windows-targets 0.53.5", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" +dependencies = [ + "windows_aarch64_gnullvm 0.48.5", + "windows_aarch64_msvc 0.48.5", + "windows_i686_gnu 0.48.5", + "windows_i686_msvc 0.48.5", + "windows_x86_64_gnu 0.48.5", + "windows_x86_64_gnullvm 0.48.5", + "windows_x86_64_msvc 0.48.5", ] [[package]] @@ -1794,64 +2535,171 @@ version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", + "windows_i686_gnullvm 0.52.6", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", +] + +[[package]] +name = "windows-targets" +version = "0.53.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" +dependencies = [ + "windows-link", + "windows_aarch64_gnullvm 0.53.1", + "windows_aarch64_msvc 0.53.1", + "windows_i686_gnu 0.53.1", + "windows_i686_gnullvm 0.53.1", + "windows_i686_msvc 0.53.1", + "windows_x86_64_gnu 0.53.1", + "windows_x86_64_gnullvm 0.53.1", + "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" +[[package]] +name = "windows_aarch64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" + [[package]] name = "windows_i686_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" +[[package]] +name = "windows_i686_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" + [[package]] name = "windows_i686_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" +[[package]] +name = "windows_i686_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" + [[package]] name = "windows_i686_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" +[[package]] +name = "windows_i686_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" +[[package]] +name = "windows_x86_64_gnu" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" +[[package]] +name = "windows_x86_64_msvc" +version = "0.53.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" + [[package]] name = "winnow" version = "0.7.13" @@ -1980,6 +2828,26 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zerocopy" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0894878a5fa3edfd6da3f88c4805f4c8558e2b996227a3d864f47fe11e38282c" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.8.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88d2b8d9c68ad2b9e4340d7832716a4d21a22a1154777ad56ea55c51a9cf3831" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.106", +] + [[package]] name = "zerofrom" version = "0.1.6" @@ -2001,6 +2869,12 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" + [[package]] name = "zerotrie" version = "0.2.2" diff --git a/examples/app-demo/crates/app-demo-core/Cargo.toml b/examples/app-demo/crates/app-demo-core/Cargo.toml index d4b8081..a963715 100644 --- a/examples/app-demo/crates/app-demo-core/Cargo.toml +++ b/examples/app-demo/crates/app-demo-core/Cargo.toml @@ -15,4 +15,5 @@ futures = { workspace = true } serde = { workspace = true } [dev-dependencies] +async-trait = { workspace = true } serde_json = { workspace = true } From d73eea5e0ee6864f5c62763fdddcd11925f80420 Mon Sep 17 00:00:00 2001 From: Christian Date: Thu, 6 Nov 2025 13:37:13 -0600 Subject: [PATCH 4/6] cargo fmt --- crates/anyedge-adapter-fastly/src/proxy.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/anyedge-adapter-fastly/src/proxy.rs b/crates/anyedge-adapter-fastly/src/proxy.rs index 5c750d1..862fd36 100644 --- a/crates/anyedge-adapter-fastly/src/proxy.rs +++ b/crates/anyedge-adapter-fastly/src/proxy.rs @@ -44,10 +44,7 @@ fn build_fastly_request( uri: &Uri, headers: HeaderMap, ) -> Result { - let mut fastly_request = FastlyRequest::new( - method.clone(), - uri.to_string(), - ); + let mut fastly_request = FastlyRequest::new(method.clone(), uri.to_string()); fastly_request.set_method(method); for (name, value) in headers.iter() { From 097a0d53e3bbe4e558a55aab3d917e3870af9781 Mon Sep 17 00:00:00 2001 From: Aram Grigoryan <132480+aram356@users.noreply.github.com> Date: Fri, 7 Nov 2025 09:59:47 -0800 Subject: [PATCH 5/6] Allow to use RequestContext extractor in action handlers --- Cargo.lock | 1 + TODO.md | 38 ++++ .../src/templates/core/src/handlers.rs.hbs | 3 +- crates/anyedge-macros/src/action.rs | 208 +++++++++++++++++- .../crates/app-demo-core/src/handlers.rs | 3 +- 5 files changed, 249 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e17100f..4f082f3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -287,6 +287,7 @@ name = "app-demo-core" version = "0.1.0" dependencies = [ "anyedge-core", + "async-trait", "bytes", "futures", "serde", diff --git a/TODO.md b/TODO.md index 550f6e7..cd41405 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,44 @@ High-level backlog and decisions to drive the next milestones. +## Current Task (expand_action_impl coverage + cleanup) +- [x] Audit `expand_action_impl` behaviour to list any untested code paths or edge cases (e.g., tuple destructuring errors, non-RC tuple structs, extractor invocation). +- [x] Add focused tests in `crates/anyedge-macros/src/action.rs` to cover the missing scenarios while keeping contract unchanged. +- [x] Simplify the implementation if warranted (e.g., helper extraction, clearer error handling) without altering observable behaviour; highlight the deltas in the review section. +- [x] Run `cargo test` workspace-wide and note results. +- [x] Record a new review entry summarising the changes, assumptions, and outstanding items. + +## Review (2025-11-07 17:52:45 UTC) +- Summary: Extracted RequestContext pattern normalisation into a helper for clearer error aggregation and broadened the macro tests to cover attribute arguments, self receivers, tuple binding mistakes, and extractor codegen so `expand_action_impl` remains well-specified. +- Assumptions: String-matching the generated `FromRequest` call stays stable because we don't plan to rename that trait or method; tuple destructuring for RequestContext will continue to expect a single binding. +- Outstanding: None; `cargo test` (workspace) succeeded after the new tests. + +## Current Task (template proxy_demo parity) +- [x] Update `crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs` so the generated `proxy_demo` matches the example handler (`#[action]` + `RequestContext(ctx): RequestContext` binding). +- [x] Run `cargo test` to ensure the template change doesn’t break the workspace. +- [x] Capture a review entry summarising the template update and any follow-ups. + +## Review (2025-11-07 17:55:17 UTC) +- Summary: Aligned the CLI template’s `proxy_demo` definition with the app demo (now tagged with `#[action]` and destructuring `RequestContext`) so generated projects inherit the same extractor ergonomics. +- Assumptions: Template consumers expect the proxy route to behave like the example app; no additional template files reference the old signature. +- Outstanding: None; `cargo test` across the workspace passed after the template tweak. + +## Current Task (RequestContext pattern support) +- [x] Teach the `#[action]` macro to accept tuple-struct style parameters like `RequestContext(ctx): RequestContext` by normalising that pattern to the owned context argument (ensure the same ownership semantics and keep duplicate checks). +- [x] Update the `proxy_demo` handler in `examples/app-demo/crates/app-demo-core/src/handlers.rs` to demonstrate the new binding style. +- [x] Run `cargo test` for the workspace and fix any regressions. +- [x] Append a new review entry (summary, assumptions, outstanding items) once the change is complete. + +## Review (2025-11-07 17:48:52 UTC) +- Summary: Normalised `RequestContext` parameters passed through `#[action]` so tuple-style bindings (e.g. `RequestContext(ctx): RequestContext`) collapse to the owned context, added regression tests covering the pattern, and showcased the syntax on `proxy_demo`. +- Assumptions: Only one owned `RequestContext` parameter should exist per handler; tuple-style bindings only contain a single pattern element. +- Outstanding: None; `cargo test` passed for the entire workspace (no warnings after the final iteration). + +## Review (2025-11-07 17:39:28 UTC) +- Summary: Extended `#[action]` to accept a single `RequestContext` parameter (with duplicate detection and helper tests) and applied the attribute to `proxy_demo`, relying on the original handler logic. +- Assumptions: `RequestContext` parameters are owned values (no reference variants needed) and only one is expected per handler. +- Outstanding: None; `cargo test` across the workspace passed after the macro test adjustment. + ## Queue (near-term) ### High Priority diff --git a/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs b/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs index 13063f8..2f266c8 100644 --- a/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs +++ b/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs @@ -65,7 +65,8 @@ pub(crate) async fn echo_json(Json(body): Json) -> Text { Text::new(format!("Hello, {}!", body.name)) } -pub(crate) async fn proxy_demo(ctx: RequestContext) -> Result { +#[action] +pub(crate) async fn proxy_demo(RequestContext(ctx): RequestContext) -> Result { let params: ProxyPath = ctx.path()?; let proxy_handle = ctx.proxy_handle(); let request = ctx.into_request(); diff --git a/crates/anyedge-macros/src/action.rs b/crates/anyedge-macros/src/action.rs index dd1b551..60388f7 100644 --- a/crates/anyedge-macros/src/action.rs +++ b/crates/anyedge-macros/src/action.rs @@ -1,6 +1,6 @@ use proc_macro::TokenStream; use quote::{format_ident, quote}; -use syn::{spanned::Spanned, FnArg, ItemFn}; +use syn::{spanned::Spanned, Error, FnArg, ItemFn, Pat, PathArguments, Type}; pub fn expand_action(attr: TokenStream, item: TokenStream) -> TokenStream { expand_action_impl(attr.into(), item.into()).into() @@ -42,8 +42,13 @@ pub(crate) fn expand_action_impl( inner_fn.vis = syn::Visibility::Inherited; inner_fn.attrs.clear(); + if let Err(err) = normalize_request_context_patterns(&mut inner_fn) { + return err.to_compile_error(); + } + let mut extract_stmts = Vec::new(); let mut arg_idents = Vec::new(); + let mut has_request_context = false; for (index, arg) in func.sig.inputs.iter().enumerate() { let pat_type = match arg { @@ -52,11 +57,24 @@ pub(crate) fn expand_action_impl( }; let ty = &pat_type.ty; + if is_request_context_type(ty) { + if has_request_context { + return syn::Error::new( + ty.span(), + "#[action] functions support at most one RequestContext argument", + ) + .to_compile_error(); + } + has_request_context = true; + arg_idents.push(quote! { __ctx }); + continue; + } + let var_ident = format_ident!("__arg{}", index); extract_stmts.push(quote! { let #var_ident = <#ty as ::anyedge_core::extractor::FromRequest>::from_request(&__ctx).await?; }); - arg_idents.push(var_ident); + arg_idents.push(quote! { #var_ident }); } let output = quote! { @@ -75,6 +93,71 @@ pub(crate) fn expand_action_impl( output } +fn is_request_context_type(ty: &Type) -> bool { + let Type::Path(type_path) = ty else { + return false; + }; + if type_path.qself.is_some() { + return false; + } + path_is_request_context(&type_path.path) +} + +fn normalize_request_context_pat(pat: &mut Box) -> syn::Result<()> { + let Some(replacement) = extract_request_context_binding(pat.as_ref())? else { + return Ok(()); + }; + *pat = Box::new(replacement); + Ok(()) +} + +fn extract_request_context_binding(pat: &Pat) -> syn::Result> { + let Pat::TupleStruct(tuple_pat) = pat else { + return Ok(None); + }; + if !path_is_request_context(&tuple_pat.path) { + return Ok(None); + } + if tuple_pat.elems.len() != 1 { + return Err(syn::Error::new( + tuple_pat.span(), + "RequestContext destructuring expects exactly one binding", + )); + } + Ok(tuple_pat.elems.first().cloned()) +} + +fn path_is_request_context(path: &syn::Path) -> bool { + path.segments + .last() + .map(|segment| { + segment.ident == "RequestContext" && matches!(segment.arguments, PathArguments::None) + }) + .unwrap_or(false) +} + +fn normalize_request_context_patterns(func: &mut ItemFn) -> Result<(), Error> { + let mut error: Option = None; + for arg in func.sig.inputs.iter_mut() { + if let FnArg::Typed(pat_type) = arg { + if is_request_context_type(&pat_type.ty) { + if let Err(err) = normalize_request_context_pat(&mut pat_type.pat) { + if let Some(existing) = error.as_mut() { + existing.combine(err); + } else { + error = Some(err); + } + } + } + } + } + + if let Some(err) = error { + return Err(err); + } + Ok(()) +} + #[cfg(test)] mod tests { use super::expand_action_impl; @@ -85,6 +168,10 @@ mod tests { tokens.to_string() } + fn collapse_whitespace(input: &str) -> String { + input.split_whitespace().collect() + } + #[test] fn wraps_async_function() { let input = quote! { @@ -111,4 +198,121 @@ mod tests { let rendered = render(output); assert!(rendered.contains("must be async")); } + + #[test] + fn rejects_attribute_arguments() { + let input = quote! { + async fn demo(ctx: ::anyedge_core::context::RequestContext) -> ::anyedge_core::http::Response { + unimplemented!() + } + }; + let output = expand_action_impl(quote!(path = "/demo"), input); + let rendered = render(output); + assert!(rendered.contains("does not accept arguments")); + } + + #[test] + fn rejects_self_receivers() { + let input = quote! { + async fn invalid(&self) -> ::anyedge_core::http::Response { + unimplemented!() + } + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + assert!(rendered.contains("does not support self receivers")); + } + + #[test] + fn allows_request_context_argument() { + let input = quote! { + async fn with_ctx( + ctx: ::anyedge_core::context::RequestContext + ) -> ::std::result::Result< + ::anyedge_core::http::Response, + ::anyedge_core::error::EdgeError + > { + let _ = ctx; + Ok(::anyedge_core::http::response_builder() + .status(::anyedge_core::http::StatusCode::OK) + .body(::anyedge_core::body::Body::empty()) + .unwrap()) + } + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + let collapsed = collapse_whitespace(&rendered); + assert!(collapsed.contains("__with_ctx_inner(__ctx)")); + } + + #[test] + fn allows_request_context_tuple_pattern_argument() { + let input = quote! { + async fn tuple_ctx( + RequestContext(ctx): ::anyedge_core::context::RequestContext + ) -> ::std::result::Result< + ::anyedge_core::http::Response, + ::anyedge_core::error::EdgeError + > { + let _ = ctx; + Ok(::anyedge_core::http::response_builder() + .status(::anyedge_core::http::StatusCode::OK) + .body(::anyedge_core::body::Body::empty()) + .unwrap()) + } + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + let collapsed = collapse_whitespace(&rendered); + assert!(collapsed.contains("__tuple_ctx_inner(__ctx)")); + } + + #[test] + fn rejects_multiple_request_context_arguments() { + let input = quote! { + async fn invalid( + first: ::anyedge_core::context::RequestContext, + second: ::anyedge_core::context::RequestContext, + ) {} + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + assert!(rendered.contains("support at most one RequestContext argument")); + } + + #[test] + fn rejects_request_context_tuple_with_multiple_bindings() { + let input = quote! { + async fn invalid( + RequestContext(a, b): ::anyedge_core::context::RequestContext + ) -> ::anyedge_core::http::Response { + unimplemented!() + } + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + assert!(rendered.contains("expects exactly one binding")); + } + + #[test] + fn generates_extractor_calls_for_arguments() { + let input = quote! { + async fn demo( + value: demo::ExtractorType + ) -> ::anyedge_core::http::Response { + let _ = value; + ::anyedge_core::http::response_builder() + .status(::anyedge_core::http::StatusCode::OK) + .body(::anyedge_core::body::Body::empty()) + .unwrap() + } + }; + let output = expand_action_impl(TokenStream::new(), input); + let rendered = render(output); + let collapsed = collapse_whitespace(&rendered); + assert!( + collapsed.contains("FromRequest>::from_request"), + "expected extractor call in generated output: {rendered}" + ); + } } diff --git a/examples/app-demo/crates/app-demo-core/src/handlers.rs b/examples/app-demo/crates/app-demo-core/src/handlers.rs index 0049e26..e486285 100644 --- a/examples/app-demo/crates/app-demo-core/src/handlers.rs +++ b/examples/app-demo/crates/app-demo-core/src/handlers.rs @@ -90,7 +90,8 @@ struct ProxyPath { rest: String, } -pub(crate) async fn proxy_demo(ctx: RequestContext) -> Result { +#[action] +pub(crate) async fn proxy_demo(RequestContext(ctx): RequestContext) -> Result { let params: ProxyPath = ctx.path()?; let proxy_handle = ctx.proxy_handle(); let request = ctx.into_request(); From 411a9a0330ccf3a78362844c450d2be52f1d71b0 Mon Sep 17 00:00:00 2001 From: Aram Grigoryan <132480+aram356@users.noreply.github.com> Date: Fri, 7 Nov 2025 12:49:12 -0800 Subject: [PATCH 6/6] Reorg TODO items --- TODO.md | 324 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 162 insertions(+), 162 deletions(-) diff --git a/TODO.md b/TODO.md index cd41405..65bf2b2 100644 --- a/TODO.md +++ b/TODO.md @@ -2,54 +2,12 @@ High-level backlog and decisions to drive the next milestones. -## Current Task (expand_action_impl coverage + cleanup) -- [x] Audit `expand_action_impl` behaviour to list any untested code paths or edge cases (e.g., tuple destructuring errors, non-RC tuple structs, extractor invocation). -- [x] Add focused tests in `crates/anyedge-macros/src/action.rs` to cover the missing scenarios while keeping contract unchanged. -- [x] Simplify the implementation if warranted (e.g., helper extraction, clearer error handling) without altering observable behaviour; highlight the deltas in the review section. -- [x] Run `cargo test` workspace-wide and note results. -- [x] Record a new review entry summarising the changes, assumptions, and outstanding items. - -## Review (2025-11-07 17:52:45 UTC) -- Summary: Extracted RequestContext pattern normalisation into a helper for clearer error aggregation and broadened the macro tests to cover attribute arguments, self receivers, tuple binding mistakes, and extractor codegen so `expand_action_impl` remains well-specified. -- Assumptions: String-matching the generated `FromRequest` call stays stable because we don't plan to rename that trait or method; tuple destructuring for RequestContext will continue to expect a single binding. -- Outstanding: None; `cargo test` (workspace) succeeded after the new tests. - -## Current Task (template proxy_demo parity) -- [x] Update `crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs` so the generated `proxy_demo` matches the example handler (`#[action]` + `RequestContext(ctx): RequestContext` binding). -- [x] Run `cargo test` to ensure the template change doesn’t break the workspace. -- [x] Capture a review entry summarising the template update and any follow-ups. - -## Review (2025-11-07 17:55:17 UTC) -- Summary: Aligned the CLI template’s `proxy_demo` definition with the app demo (now tagged with `#[action]` and destructuring `RequestContext`) so generated projects inherit the same extractor ergonomics. -- Assumptions: Template consumers expect the proxy route to behave like the example app; no additional template files reference the old signature. -- Outstanding: None; `cargo test` across the workspace passed after the template tweak. - -## Current Task (RequestContext pattern support) -- [x] Teach the `#[action]` macro to accept tuple-struct style parameters like `RequestContext(ctx): RequestContext` by normalising that pattern to the owned context argument (ensure the same ownership semantics and keep duplicate checks). -- [x] Update the `proxy_demo` handler in `examples/app-demo/crates/app-demo-core/src/handlers.rs` to demonstrate the new binding style. -- [x] Run `cargo test` for the workspace and fix any regressions. -- [x] Append a new review entry (summary, assumptions, outstanding items) once the change is complete. - -## Review (2025-11-07 17:48:52 UTC) -- Summary: Normalised `RequestContext` parameters passed through `#[action]` so tuple-style bindings (e.g. `RequestContext(ctx): RequestContext`) collapse to the owned context, added regression tests covering the pattern, and showcased the syntax on `proxy_demo`. -- Assumptions: Only one owned `RequestContext` parameter should exist per handler; tuple-style bindings only contain a single pattern element. -- Outstanding: None; `cargo test` passed for the entire workspace (no warnings after the final iteration). - -## Review (2025-11-07 17:39:28 UTC) -- Summary: Extended `#[action]` to accept a single `RequestContext` parameter (with duplicate detection and helper tests) and applied the attribute to `proxy_demo`, relying on the original handler logic. -- Assumptions: `RequestContext` parameters are owned values (no reference variants needed) and only one is expected per handler. -- Outstanding: None; `cargo test` across the workspace passed after the macro test adjustment. - ## Queue (near-term) ### High Priority -- [ ] CI: add `fmt`, `clippy`, and `test` workflows -- [ ] CLI: `anyedge build --adapter fastly|cloudflare` -- [ ] CLI: `anyedge deploy --adapter fastly|cloudflare` - [ ] Core: `Response::json` behind `serde` feature - [ ] Fastly proxy: add tests for backend send + header/body mapping - [ ] Cloudflare streaming: map `Response::with_chunks` to `ReadableStream` with backpressure -- [ ] Cloudflare demo: add minimal `wrangler` example and verify `wrangler dev` - [ ] Core proxy: add async fetch facade (feature `async-client`) and implement Cloudflare proxy ### Medium Priority @@ -59,8 +17,10 @@ High-level backlog and decisions to drive the next milestones. - [ ] Docs: add RouteOptions + streaming policy section (examples done; expand README section) ### Completed / Ongoing Maintenance -- [x] CLI: `anyedge build --adapter fastly` to package a Fastly Compute@Edge artifact -- [x] CLI: `anyedge deploy --adapter fastly` using Fastly CLI/API +- [x] CLI: manifest-driven `anyedge build --adapter fastly|cloudflare|axum` wiring via `crates/anyedge-cli/src/main.rs` + adapter manifests. +- [x] CLI: manifest-driven `anyedge deploy --adapter fastly|cloudflare` wrappers that call Fastly CLI or `wrangler` per manifest config. +- [x] CI: workspace `fmt`, `clippy`, and `test` workflows (`.github/workflows/format.yml`, `.github/workflows/test.yml`). +- [x] Cloudflare demo: runnable `wrangler` example under `examples/app-demo/crates/app-demo-adapter-cloudflare` (with `wrangler.toml` + README instructions). - [x] Core: helper to fetch all header values for a name (multi-value support) - [x] Docs: clean stale references to removed hello example from README/targets - [x] Docs: highlight controller-based workflow and update examples @@ -79,7 +39,7 @@ High-level backlog and decisions to drive the next milestones. - [x] Controller: cover negative paths (`State` missing, `ValidatedJson` errors) and assert returned status/body. ## Milestones -- [ ] Fastly adapter MVP +- [x] Fastly adapter MVP - [x] Map Fastly Request -> `anyedge-core::Request` - [x] Map `anyedge-core::Response` -> Fastly Response (headers/body) - [x] Handle binary/text bodies and content-length @@ -89,15 +49,15 @@ High-level backlog and decisions to drive the next milestones. - [x] Basic mapping: Workers Request -> AnyEdge Request - [x] Basic mapping: AnyEdge Response -> Workers Response (buffered bodies) - [ ] Streaming behavior (ReadableStream) and backpressure - - [ ] Example: deploy sample with `wrangler` (`examples/app-demo/crates/app-demo-adapter-cloudflare`) + - [x] Example: deploy sample with `wrangler` (`examples/app-demo/crates/app-demo-adapter-cloudflare`) - [ ] CLI - [x] `anyedge new `: scaffold an app (lib with `build_app()`) - - [ ] `anyedge build --adapter fastly|cloudflare` - - [ ] `anyedge deploy --adapter fastly|cloudflare` + - [x] `anyedge build --adapter fastly|cloudflare` + - [x] `anyedge deploy --adapter fastly|cloudflare` - [ ] `anyedge dev` improvements: better HTTP parsing, hot-reload -- [ ] Config - - [ ] `anyedge.toml`: app name, routes, provider-specific settings - - [ ] Secrets/ENV strategy and provider bindings +- [x] Config + - [x] `anyedge.toml`: app name, routes, provider-specific settings + - [x] Secrets/ENV strategy and provider bindings - [ ] Observability - [ ] Logging levels; feature-gated tracing - [ ] Metrics hooks; request timing middleware @@ -114,8 +74,8 @@ High-level backlog and decisions to drive the next milestones. - [ ] Provider guides (Fastly, Cloudflare) - [ ] CLI reference - [ ] Example cookbook -- [ ] CI - - [ ] Run `cargo fmt`, `cargo clippy`, and tests +- [x] CI + - [x] Run `cargo fmt`, `cargo clippy`, and tests ## Roadmap (2025-09-24) - [x] Adapter stability: formalise the provider adapter contract (request/response mapping, streaming guarantees, proxy hooks) and capture it in shared docs + integration tests so new targets plug in safely. (`docs/adapter-contract.md`, Fastly contract tests under `crates/anyedge-adapter-fastly/tests/contract.rs`, Cloudflare contract tests under `crates/anyedge-adapter-cloudflare/tests/contract.rs`, manifest schema in `docs/manifest.md`) @@ -123,6 +83,19 @@ High-level backlog and decisions to drive the next milestones. - [x] Manifest ergonomics: design an `anyedge.toml` schema that mirrors Spin’s manifest convenience (route triggers, env/secrets, build targets) while remaining provider-agnostic; update CLI scaffolding accordingly. (`crates/anyedge-cli/src/manifest.rs`, templates in `crates/anyedge-cli/src/templates/root/anyedge.toml.hbs`, doc `docs/manifest.md`, app-demo manifest `examples/app-demo/anyedge.toml`) - [ ] Tooling parity: extend `anyedge-cli` with template/plugin style commands (similar to Spin templates) to streamline new app scaffolds and provider-specific wiring. +## Open Design Questions (for later pickup) +- Provider priorities: focus on Fastly Compute@Edge, then Cloudflare Workers. +- Minimum Rust version (MSRV) target. +- Async story: keep core sync or introduce async features (Tokio) behind flags? +- Request/Response mapping rules (header casing, multi-value headers, binary bodies). +- Caching/edge-specific headers: how much to standardize (e.g., Surrogate-Control)? +- Dev UX: integrate a local hyper server behind a feature vs. keeping zero-deps TCP server. +- Packaging/deploy: preferred tooling (Fastly CLI/API; AWS SAM/CDK or native Lambda tooling). +- Config format: TOML/JSON/YAML; env overlays. +- License and contribution guidelines. + +## Execution Log + ## Codex Plan (2024-05-07) - [x] Review repository guides (`README.md`, `AGENTS.md`) to capture stated goals and workflows. - [x] Map the crate layout by skimming `Cargo.toml` and key crate README/doc comments. @@ -135,17 +108,6 @@ High-level backlog and decisions to drive the next milestones. - Supporting crates include `anyedge-std` for stdout logging, `anyedge-cli` for dev server + scaffolding, and demo workspaces under `examples/app-demo` to validate provider flows. - Workspace `Cargo.toml` keeps default members lean (core only) to support offline builds; additional crates are opt-in via features when targeting specific adapters. -## Open Design Questions (for later pickup) -- Provider priorities: focus on Fastly Compute@Edge, then Cloudflare Workers. -- Minimum Rust version (MSRV) target. -- Async story: keep core sync or introduce async features (Tokio) behind flags? -- Request/Response mapping rules (header casing, multi-value headers, binary bodies). -- Caching/edge-specific headers: how much to standardize (e.g., Surrogate-Control)? -- Dev UX: integrate a local hyper server behind a feature vs. keeping zero-deps TCP server. -- Packaging/deploy: preferred tooling (Fastly CLI/API; AWS SAM/CDK or native Lambda tooling). -- Config format: TOML/JSON/YAML; env overlays. -- License and contribution guidelines. - ## Codex Plan (2025-09-18 - Validation Extractors) - [x] Review existing parameter/body extractors to identify integration points for validator-backed wrappers. - [x] Implement validated variants for path/query (and other relevant) extractors reusing `validator::Validate`. @@ -157,6 +119,11 @@ High-level backlog and decisions to drive the next milestones. - [x] Introduce a `ValidateJson` alias (or equivalent helper) that reuses `ValidatedJson`. - [x] Update docs/tests to reference the new alias where appropriate and log the change in this TODO review. +## Codex Plan (2025-09-18 - Remove ValidateJson Alias) +- [x] Remove the `ValidateJson` wrapper from extractors/tests/exports, keeping `ValidatedJson` as the canonical helper. +- [x] Revert docs and TODO review notes referencing `ValidateJson`. +- [x] Re-run controller crate tests to confirm everything still passes. + ## Review (2025-09-18 02:10 UTC) - Recorded a three-step familiarization plan, executed documentation + crate walkthrough, and captured architectural notes under the plan section. - Assumed existing docs (`README.md`, `AGENTS.md`) are the latest sources of truth; no discrepancies observed during review. @@ -167,11 +134,6 @@ High-level backlog and decisions to drive the next milestones. - Added targeted unit tests verifying both success and failure cases for validated path/query extraction; `cargo test -p anyedge-controller` passes. - No additional assumptions beyond existing validation behaviour; no unresolved issues noted. -## Codex Plan (2025-09-18 - Remove ValidateJson Alias) -- [x] Remove the `ValidateJson` wrapper from extractors/tests/exports, keeping `ValidatedJson` as the canonical helper. -- [x] Revert docs and TODO review notes referencing `ValidateJson`. -- [x] Re-run controller crate tests to confirm everything still passes. - ## Review (2025-09-18 02:21 UTC) - Removed the redundant `ValidateJson` wrapper per updated guidance, keeping `ValidatedJson` as the single validator-backed JSON extractor. - Cleaned README/TODO references accordingly and pruned alias-specific tests; `cargo test -p anyedge-controller` still passes. @@ -190,11 +152,6 @@ High-level backlog and decisions to drive the next milestones. - [x] Confirm current workspace layout to know which `cargo` commands exercise all crates. - [x] Advise user on running full test suite and targeted variants as needed. -## Review (2025-09-19 15:25 UTC) -- Noted workspace members/default-members to explain why `cargo test` covers only core by default. -- Documented commands for running all workspace tests plus targeted crates and feature gates. -- No code changes required; guidance only. - ## Codex Plan (2025-09-19 - Fix anyedge-fastly Tests) - [x] Reproduce `cargo test -p anyedge-fastly` failure to capture the exact error. *(Unable to reproduce; command succeeds locally.)* - [x] Inspect relevant sources/tests to identify root cause. *(Fastly feature requires `wasm32-wasip1` target; host builds fall back to stub with no tests.)* @@ -207,75 +164,34 @@ High-level backlog and decisions to drive the next milestones. - [x] Implement shell script to orchestrate the checks with Fastly-specific handling. - [x] Document script usage and outcomes in TODO review section with timestamp. -## Review (2025-09-19 15:55 UTC) -- Added `scripts/run_tests.sh` (initially `run_all_checks.sh`) to bundle fmt, clippy, and workspace tests while excluding the wasm-only Fastly demo during host runs. -- Script verifies `wasm32-wasip1` availability and builds both the Fastly adapter (`anyedge-fastly` with `fastly` feature) and demo binary for the wasm target to cover edge-only code paths. -- Provides a single entry point for comprehensive validation; Fastly tests remain blocked on native hosts, so wasm builds act as the smoke check. - ## Codex Plan (2025-09-19 - Test Script Adjustments) - [x] Define the reduced test-only scope for `scripts/run_tests.sh`, including Fastly wasm coverage. - [x] Update the script to drop fmt/clippy/build steps and run the desired test commands (host + wasm). - [x] Ensure script messaging guides users when Fastly wasm tests cannot run (e.g., Viceroy keychain issues). - [x] Record the changes and remaining caveats in TODO review section with timestamp. -## Review (2025-09-19 16:05 UTC) -- Trimmed `scripts/run_tests.sh` to a test-only flow: workspace tests (excluding `app-demo-adapter-fastly`), Fastly CLI tests, and wasm32 `fastly` feature tests run from the adapter crate. -- Added failure guidance when Viceroy cannot access macOS keychain certificates; users can set `SSL_CERT_FILE` or run where a keychain is available before retrying. -- Command still surfaces the Fastly wasm failure in this sandbox (certificate issue), but other suites pass; no additional code changes required. - ## Codex Plan (2025-09-19 - Test Script UX) - [x] Decide on section markers/format for clearer script output. - [x] Update `scripts/run_tests.sh` to print section headers around each major test group. - [x] Verify the script still exits with helpful guidance on wasm failures. - [x] Log the changes in TODO review section with timestamp. -## Review (2025-09-19 16:15 UTC) -- Added bold section separators around workspace, Fastly CLI, and wasm test phases in `scripts/run_tests.sh` for easier scanning. -- Confirmed the wasm phase still surfaces the keychain guidance when Viceroy fails; other sections remain unaffected. -- No code changes beyond the script; tests behave as before (wasm step still blocked in sandbox environment). - ## Codex Plan (2025-09-19 - Simplify Wasm Failure Messaging) - [x] Remove custom failure messaging in `scripts/run_tests.sh` so wasm tests fail like other sections. - [x] Verify script behaviour post-change. - [x] Update TODO review section with outcome and timestamp. -## Review (2025-09-19 16:25 UTC) -- Dropped the custom Viceroy guidance in `scripts/run_tests.sh`; now all phases use `run` and rely on `set -e` for failures. -- Confirmed workspace and Fastly CLI sections still pass while wasm tests fail with the raw keychain error (expected in this sandbox). -- No additional adjustments required. - ## Codex Plan (2025-09-19 - Script Preflight Checks) - [x] Consolidate binary/target verification at the top of `scripts/run_tests.sh`. - [x] Ensure checks cover both `cargo`, `rustup`, and wasm target before any tests run. - [x] Validate script after refactor and document changes in TODO review. -## Review (2025-09-19 16:32 UTC) -- Preflight now checks for `cargo`, `rustup`, and the `wasm32-wasip1` target before any test phases run, ensuring early exits on missing tooling. -- Post-change run confirms behaviour: host tests pass, Fastly wasm still fails due to Viceroy keychain access in this sandbox—expected. -- No further adjustments needed. - ## Codex Plan (2025-09-19 - Controller Streaming Options) - [x] Inspect controller `RouteSet`/`RouteSpec` to identify extension points for route-level body mode. - [x] Implement API changes allowing controllers to opt into streaming/buffered modes and wire through to core router. - [x] Add tests covering streaming behaviour via controller routes. - [x] Document changes in TODO review section with timestamp. -## Review (2025-09-19 16:45 UTC) -- Added per-route body mode to controller `RouteSpec`/`RouteEntry`, enabling callers to supply `RouteOptions` (e.g. streaming/buffered) that are preserved when applying routes to the core app. -- Introduced `RouteSet::push_entry` helper so nested/merged route sets keep their body configuration. -- Extended controller tests to cover streaming coercion and buffered rejection paths via the new API; `cargo test -p anyedge-controller` passes. - -## Review (2025-09-19 01:28 UTC) -- Rebuilt `app-demo-core` against the redesigned `anyedge-core` by wiring routes through `RouterService::builder`, swapping controller extractors for `anyedge_core` equivalents, and preserving the streaming example via `Body::stream`. -- Updated Fastly and Cloudflare entrypoints to rely on the adapter `dispatch` helpers, returning converted fallback responses when adapter conversion fails so we avoid propagating runtime errors. -- Tests: `cargo test -p app-demo-core`, `cargo check -p app-demo-adapter-fastly`; Cloudflare host build (`cargo check -p app-demo-adapter-cloudflare`) still fails in `worker` 0.0.24 because `js_sys::Iterator` lacks `unwrap` on this toolchain—matches the prior dev warning and needs upstream crate updates for host checks. -- Assumptions: routing defaults (no auto OPTIONS) remain acceptable for the demo; Cloudflare fallback uses `Response::error` to surface adapter failures until `worker` exposes richer constructors. - -## Review (2025-09-19 01:47 UTC) -- Removed the `worker_logger` dependency (source of the legacy `worker 0.0.24` transitive pull) and replaced it with a minimal `console_log!`-backed logger inside `anyedge-adapter-cloudflare`, so host builds only compile the current `worker 0.6` tree. -- Updated the Fastly/Cloudflare demos to call the adapter crates directly (correct crate ids) and gated the Cloudflare fetch handler behind `target_arch = "wasm32"` so x86 test builds don’t require Worker-only APIs. -- Docs now reference the new logging flow, and `cargo test` across the workspace succeeds after the change. - ## Codex Plan (2025-09-19 - App Demo Migration to Redesigned Core) - [x] Audit the app-demo crates to map controller-era APIs to the redesigned `anyedge-core` interfaces. - [x] Refactor `app-demo-core` handlers and routing to the new builder/extractor patterns, keeping streaming coverage intact. @@ -294,23 +210,12 @@ High-level backlog and decisions to drive the next milestones. - [x] Ensure any docs or templates referencing Fastly logging stay accurate. - [x] Run `cargo test` to confirm the refactor behaves as before. -## Review (2025-09-19 01:50 UTC) -- Split Fastly logging into a `logger.rs` module (mirroring Cloudflare) and re-exported it from the adapter, keeping `log_fastly` usage behind the wasm+feature gate. -- No call-site changes were required—existing demos already target `anyedge_adapter_fastly::init_logger()`—but the shared structure makes the adapters consistent. -- `cargo test` still passes; the `log_fastly` manifest warning persists (pre-existing). - ## Codex Plan (2025-09-19 - Code Coverage Investigation) - [x] Survey current test command usage to see if any coverage tooling is documented or scripted. - [x] Evaluate Rust-friendly coverage options (e.g. `cargo llvm-cov`, `grcov`) for compatibility with the workspace (wasm targets, feature flags). - [x] Prototype a coverage run on a representative crate (likely `anyedge-core`) to gauge feasibility and capture required tooling steps. - [x] Summarize recommended approach, prerequisites, and open questions in TODO review notes. -## Review (2025-09-19 01:56 UTC) -- Confirmed coverage isn’t wired into existing scripts; `scripts/run_tests.sh` strictly runs host + wasm tests without instrumentation. -- Verified `cargo-llvm-cov` is available via `asdf` and works against host crates: `cargo llvm-cov --package anyedge-core --lcov --output-path target/coverage/anyedge-core.lcov` produced an LCOV file and summary (~52% line coverage for `anyedge-core`, `proc` modules currently untested). -- Suggested path forward: document `cargo llvm-cov` usage (including creating `target/coverage/`), limit runs to host-capable crates, and treat wasm-only crates as out-of-scope unless a wasm coverage workflow is introduced. -- Next steps could include adding a helper script and/or CI job if coverage reporting becomes a target metric. - ## Codex Plan (2025-09-19 - Core Coverage Backfill) - [x] Expand unit tests for `anyedge_core::context::RequestContext` to cover extraction success/failure, JSON/form parsing, and path/query edge cases. - [x] Add tests for `anyedge_core::error::EdgeError` constructors and conversion paths, ensuring status codes + messages are asserted. @@ -320,28 +225,50 @@ High-level backlog and decisions to drive the next milestones. - [x] Add compile-fail or snapshot tests for the `anyedge-macros::action` proc macro to cover unsupported inputs. - [x] Run `cargo llvm-cov --package anyedge-core` (and any new test suites) to validate coverage improvements. -## Review (2025-09-19 02:08 UTC) -- Added focused unit tests across `anyedge-core` for request contexts (path/query/json/form), error helpers, middleware chaining, bodies/responses, extractors, and responders; mirrored coverage for the `#[action]` macro via direct `expand_action_impl` assertions. -- Reworked Clockflare/Fastly-specific comparisons where necessary (stringy path params, async middleware helpers) so the new tests reflect real behaviour. -- `cargo test` passes, and `cargo llvm-cov --package anyedge-core --summary-only` now reports ~69% line coverage (up from ~52%); extractor/macro modules remain partially uncovered but key runtime surfaces are exercised. - ## Codex Plan (2025-09-19 - App Demo Workspace Dependencies) - [x] Switch app-demo crates to consume workspace-shared dependencies (`{ workspace = true }`) for core libraries and tooling. - [x] Ensure root `Cargo.toml` workspace dependencies cover the required crates (adding any missing entries). - [x] Update adapter/demo crate manifests to drop redundant version/specification lines in favour of workspace references. - [x] Run `cargo test` (or targeted checks) to confirm builds remain healthy. -## Review (2025-09-19 02:12 UTC) -- Added workspace dependency bindings for `anyedge-core`, adapters, demos, `fastly`, and `worker` in the root manifest, then pointed the app-demo crates at them so they share versions with the framework. -- Demo manifests now rely on `{ workspace = true }` for `anyedge-adapter-*`, `app-demo-core`, `log`, `serde`, `fastly`, and `worker`, removing bespoke paths/versions. -- `cargo test` passes across the workspace after the manifest refactors. - ## Codex Plan (2025-09-19 - Fastly SDK 0.11 Migration) - [ ] Update the Fastly adapter to compile against `fastly` 0.11 APIs (request building, async streaming, response conversion). - [ ] Adjust logging helper to the new log-fastly builder API. - [ ] Ensure proxy tests/builds pass for streaming + compression paths. - [ ] Verify the app demos compile for `wasm32-wasip1` with the updated SDK. +## Review (2025-09-19 01:28 UTC) +- Rebuilt `app-demo-core` against the redesigned `anyedge-core` by wiring routes through `RouterService::builder`, swapping controller extractors for `anyedge_core` equivalents, and preserving the streaming example via `Body::stream`. +- Updated Fastly and Cloudflare entrypoints to rely on the adapter `dispatch` helpers, returning converted fallback responses when adapter conversion fails so we avoid propagating runtime errors. +- Tests: `cargo test -p app-demo-core`, `cargo check -p app-demo-adapter-fastly`; Cloudflare host build (`cargo check -p app-demo-adapter-cloudflare`) still fails in `worker` 0.0.24 because `js_sys::Iterator` lacks `unwrap` on this toolchain—matches the prior dev warning and needs upstream crate updates for host checks. +- Assumptions: routing defaults (no auto OPTIONS) remain acceptable for the demo; Cloudflare fallback uses `Response::error` to surface adapter failures until `worker` exposes richer constructors. + +## Review (2025-09-19 01:47 UTC) +- Removed the `worker_logger` dependency (source of the legacy `worker 0.0.24` transitive pull) and replaced it with a minimal `console_log!`-backed logger inside `anyedge-adapter-cloudflare`, so host builds only compile the current `worker 0.6` tree. +- Updated the Fastly/Cloudflare demos to call the adapter crates directly (correct crate ids) and gated the Cloudflare fetch handler behind `target_arch = "wasm32"` so x86 test builds don’t require Worker-only APIs. +- Docs now reference the new logging flow, and `cargo test` across the workspace succeeds after the change. + +## Review (2025-09-19 01:50 UTC) +- Split Fastly logging into a `logger.rs` module (mirroring Cloudflare) and re-exported it from the adapter, keeping `log_fastly` usage behind the wasm+feature gate. +- No call-site changes were required—existing demos already target `anyedge_adapter_fastly::init_logger()`—but the shared structure makes the adapters consistent. +- `cargo test` still passes; the `log_fastly` manifest warning persists (pre-existing). + +## Review (2025-09-19 01:56 UTC) +- Confirmed coverage isn’t wired into existing scripts; `scripts/run_tests.sh` strictly runs host + wasm tests without instrumentation. +- Verified `cargo-llvm-cov` is available via `asdf` and works against host crates: `cargo llvm-cov --package anyedge-core --lcov --output-path target/coverage/anyedge-core.lcov` produced an LCOV file and summary (~52% line coverage for `anyedge-core`, `proc` modules currently untested). +- Suggested path forward: document `cargo llvm-cov` usage (including creating `target/coverage/`), limit runs to host-capable crates, and treat wasm-only crates as out-of-scope unless a wasm coverage workflow is introduced. +- Next steps could include adding a helper script and/or CI job if coverage reporting becomes a target metric. + +## Review (2025-09-19 02:08 UTC) +- Added focused unit tests across `anyedge-core` for request contexts (path/query/json/form), error helpers, middleware chaining, bodies/responses, extractors, and responders; mirrored coverage for the `#[action]` macro via direct `expand_action_impl` assertions. +- Reworked Clockflare/Fastly-specific comparisons where necessary (stringy path params, async middleware helpers) so the new tests reflect real behaviour. +- `cargo test` passes, and `cargo llvm-cov --package anyedge-core --summary-only` now reports ~69% line coverage (up from ~52%); extractor/macro modules remain partially uncovered but key runtime surfaces are exercised. + +## Review (2025-09-19 02:12 UTC) +- Added workspace dependency bindings for `anyedge-core`, adapters, demos, `fastly`, and `worker` in the root manifest, then pointed the app-demo crates at them so they share versions with the framework. +- Demo manifests now rely on `{ workspace = true }` for `anyedge-adapter-*`, `app-demo-core`, `log`, `serde`, `fastly`, and `worker`, removing bespoke paths/versions. +- `cargo test` passes across the workspace after the manifest refactors. + ## Review (2025-09-19 02:35 UTC) - Temporary stopgap: adapter builds against Fastly 0.11 by buffering request/response bodies and wiring a new logging helper; wasm demo (`cargo build -p app-demo-adapter-fastly --target wasm32-wasip1`) and `cargo test` now succeed. - Regression: streaming proxy behaviour (and streaming decompression) is currently disabled because bodies are buffered; follow-up work is required to restore async streaming under the new SDK. @@ -350,6 +277,41 @@ High-level backlog and decisions to drive the next milestones. - Updated `anyedge_adapter_fastly::dispatch` to surface `fastly::Error` directly; demo entrypoints can now return `dispatch(&app, req)` without hand-rolling fallback responses. - Header and request conversions match the Fastly 0.11 API, `cargo test` and `cargo build -p app-demo-adapter-fastly --target wasm32-wasip1` remain green. +## Review (2025-09-19 15:25 UTC) +- Noted workspace members/default-members to explain why `cargo test` covers only core by default. +- Documented commands for running all workspace tests plus targeted crates and feature gates. +- No code changes required; guidance only. + +## Review (2025-09-19 15:55 UTC) +- Added `scripts/run_tests.sh` (initially `run_all_checks.sh`) to bundle fmt, clippy, and workspace tests while excluding the wasm-only Fastly demo during host runs. +- Script verifies `wasm32-wasip1` availability and builds both the Fastly adapter (`anyedge-fastly` with `fastly` feature) and demo binary for the wasm target to cover edge-only code paths. +- Provides a single entry point for comprehensive validation; Fastly tests remain blocked on native hosts, so wasm builds act as the smoke check. + +## Review (2025-09-19 16:05 UTC) +- Trimmed `scripts/run_tests.sh` to a test-only flow: workspace tests (excluding `app-demo-adapter-fastly`), Fastly CLI tests, and wasm32 `fastly` feature tests run from the adapter crate. +- Added failure guidance when Viceroy cannot access macOS keychain certificates; users can set `SSL_CERT_FILE` or run where a keychain is available before retrying. +- Command still surfaces the Fastly wasm failure in this sandbox (certificate issue), but other suites pass; no additional code changes required. + +## Review (2025-09-19 16:15 UTC) +- Added bold section separators around workspace, Fastly CLI, and wasm test phases in `scripts/run_tests.sh` for easier scanning. +- Confirmed the wasm phase still surfaces the keychain guidance when Viceroy fails; other sections remain unaffected. +- No code changes beyond the script; tests behave as before (wasm step still blocked in sandbox environment). + +## Review (2025-09-19 16:25 UTC) +- Dropped the custom Viceroy guidance in `scripts/run_tests.sh`; now all phases use `run` and rely on `set -e` for failures. +- Confirmed workspace and Fastly CLI sections still pass while wasm tests fail with the raw keychain error (expected in this sandbox). +- No additional adjustments required. + +## Review (2025-09-19 16:32 UTC) +- Preflight now checks for `cargo`, `rustup`, and the `wasm32-wasip1` target before any test phases run, ensuring early exits on missing tooling. +- Post-change run confirms behaviour: host tests pass, Fastly wasm still fails due to Viceroy keychain access in this sandbox—expected. +- No further adjustments needed. + +## Review (2025-09-19 16:45 UTC) +- Added per-route body mode to controller `RouteSpec`/`RouteEntry`, enabling callers to supply `RouteOptions` (e.g. streaming/buffered) that are preserved when applying routes to the core app. +- Introduced `RouteSet::push_entry` helper so nested/merged route sets keep their body configuration. +- Extended controller tests to cover streaming coercion and buffered rejection paths via the new API; `cargo test -p anyedge-controller` passes. + ## Codex Plan (2025-09-20 - Wasm Runner Docs) - [x] Identify the best documentation spot (likely `README.md`) for Wasmtime/Viceroy installation instructions. - [x] Draft concise install steps for Wasmtime and Viceroy, ensuring commands work on macOS/Linux. @@ -361,12 +323,6 @@ High-level backlog and decisions to drive the next milestones. - [x] Identify minimal fixes or configuration adjustments to get wasm tests passing again (no implementation yet). - [x] Summarize findings and proposed solution in response; note blockers if unresolved. -## Review (2025-09-20 21:30 UTC) -- Added Wasmtime/Viceroy installation guidance plus runner instructions to `README.md` so wasm tests list their runtime prerequisites explicitly. -- Reproduced the Fastly wasm test failure: Viceroy runner aborts with “No keychain is available” while loading native certs, preventing tests from executing. -- Proposed using Wasmtime as the `wasm32-wasip1` test runner (via env override or `.cargo/config` adjustment) or configuring Viceroy to skip the system trust store; left implementation for follow-up. -- Logged the failing `cargo test` output in `debug.md` for future reference; no code changes were made to the adapter runtime itself. - ## Codex Plan (2025-09-20 - Async Compression Adapters) - [x] Add `async-compression` dependency (using workspace versioning) and wire it into Fastly/Cloudflare adapter manifests. - [x] Refactor Fastly adapter response/body decoding to use `GzipDecoder`/`BrotliDecoder` from `async-compression`, removing custom `flate2` state machines. @@ -374,12 +330,6 @@ High-level backlog and decisions to drive the next milestones. - [x] Run targeted tests (`cargo test --features fastly`, `cargo test --features cloudflare`) to confirm gzip/brotli decoding paths. - [x] Update docs (if needed) to reflect the new dependency or behaviour. -## Review (2025-09-20 22:05 UTC) -- Added `async-compression` as a workspace dependency and enabled it in both adapter manifests to centralise gzip/brotli handling. -- Replaced the bespoke `flate2`/`brotli` state machines in Fastly and Cloudflare adapters with shared `GzipDecoder`/`BrotliDecoder` pipelines over `StreamReader`. -- Host-side adapter tests pass (`cargo test -p anyedge-adapter-fastly`, `cargo test -p anyedge-adapter-cloudflare`); wasm targets still require platform runners but behaviour is unchanged. -- Documentation already covered gzip/brotli support, so no content updates were necessary beyond noting the new dependency in review. - ## Codex Plan (2025-09-20 - Core Compression Helpers) - [x] Introduce a compression helper module in `anyedge-core` that exposes shared gzip/brotli decoding for `TryStream>>` inputs. - [x] Update Fastly adapter to use the new core helper instead of its local `decode_*` implementations. @@ -387,37 +337,87 @@ High-level backlog and decisions to drive the next milestones. - [x] Add unit tests in `anyedge-core` covering gzip/brotli decoding via the helper. - [x] Re-run adapter/core tests to confirm everything compiles and passes. -## Review (2025-09-20 22:45 UTC) -- Added `compression.rs` to `anyedge-core` exposing shared `decode_gzip_stream`/`decode_brotli_stream` helpers over `async-compression`, plus unit tests that confirm round-tripping gzip and brotli blocks. -- Fastly and Cloudflare adapters now call the core helpers, removing duplicated decoder loops and dropping their direct `async-compression` dependency. -- Workspace dependencies updated (`async-stream` shared, `futures` promoted for core) and host tests pass (`cargo test -p anyedge-core`, `cargo test -p anyedge-adapter-fastly`, `cargo test -p anyedge-adapter-cloudflare`). - ## Codex Plan (2025-09-20 - Cloudflare Wasm MapErr Fix) - [x] Restore the `TryStreamExt` import in the Cloudflare adapter so `map_err` resolves for wasm builds. - [x] Run `cargo test --features cloudflare --target wasm32-wasip1 -- --nocapture` to confirm the wasm build clears (runner failures aside). -## Review (2025-09-20 22:58 UTC) -- Re-added `futures_util::TryStreamExt` to the Cloudflare adapter so `ByteStream::map_err` compiles for wasm targets. -- `cargo test --features cloudflare --target wasm32-wasip1 -- --nocapture` now builds the wasm binary; execution still fails under Wasmtime because Workers headers rely on wasm-bindgen imports unavailable in this runtime, which matches prior expectations. - ## Codex Plan (2025-09-20 - Cloudflare Demo Build Fix) - [x] Add the missing `main` entrypoint in `examples/app-demo/crates/app-demo-adapter-cloudflare/src/main.rs` (call the adapter handler). - [x] Bring `anyedge_core::response::IntoResponse` into scope or adjust error handling so `EdgeError` converts correctly. - [x] Drop unused `Write` import in the Cloudflare adapter after the refactor. - [x] Re-run `cargo build -p app-demo-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown` to confirm the demo compiles. -## Review (2025-09-20 23:10 UTC) -- Added `#![cfg_attr(target_arch = "wasm32", no_main)]` and imported `anyedge_core::response::IntoResponse` so the Cloudflare demo binary compiles to wasm without missing entrypoint errors; error handling now converts `EdgeError` via `into_response`. -- Cleaned up the Cloudflare adapter’s stale `Write` import and set the demo crate to depend on `anyedge-core` explicitly. -- `cargo build -p app-demo-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown` completes successfully (only standard warnings remain). - ## Codex Plan (2025-09-20 - Cloudflare Entry Simplification) - [x] Update Cloudflare adapter `dispatch` to return `worker::Result` so callers can propagate errors directly. - [x] Simplify the demo entrypoint to mirror the Fastly example (build app, init logger, call `dispatch`). - [x] Rebuild the Cloudflare demo for wasm to confirm no regressions. +## Review (2025-09-20 21:30 UTC) +- Added Wasmtime/Viceroy installation guidance plus runner instructions to `README.md` so wasm tests list their runtime prerequisites explicitly. +- Reproduced the Fastly wasm test failure: Viceroy runner aborts with “No keychain is available” while loading native certs, preventing tests from executing. +- Proposed using Wasmtime as the `wasm32-wasip1` test runner (via env override or `.cargo/config` adjustment) or configuring Viceroy to skip the system trust store; left implementation for follow-up. +- Logged the failing `cargo test` output in `debug.md` for future reference; no code changes were made to the adapter runtime itself. + +## Review (2025-09-20 22:05 UTC) +- Added `async-compression` as a workspace dependency and enabled it in both adapter manifests to centralise gzip/brotli handling. +- Replaced the bespoke `flate2`/`brotli` state machines in Fastly and Cloudflare adapters with shared `GzipDecoder`/`BrotliDecoder` pipelines over `StreamReader`. +- Host-side adapter tests pass (`cargo test -p anyedge-adapter-fastly`, `cargo test -p anyedge-adapter-cloudflare`); wasm targets still require platform runners but behaviour is unchanged. +- Documentation already covered gzip/brotli support, so no content updates were necessary beyond noting the new dependency in review. + +## Review (2025-09-20 22:45 UTC) +- Added `compression.rs` to `anyedge-core` exposing shared `decode_gzip_stream`/`decode_brotli_stream` helpers over `async-compression`, plus unit tests that confirm round-tripping gzip and brotli blocks. +- Fastly and Cloudflare adapters now call the core helpers, removing duplicated decoder loops and dropping their direct `async-compression` dependency. +- Workspace dependencies updated (`async-stream` shared, `futures` promoted for core) and host tests pass (`cargo test -p anyedge-core`, `cargo test -p anyedge-adapter-fastly`, `cargo test -p anyedge-adapter-cloudflare`). + +## Review (2025-09-20 22:58 UTC) +- Re-added `futures_util::TryStreamExt` to the Cloudflare adapter so `ByteStream::map_err` compiles for wasm targets. +- `cargo test --features cloudflare --target wasm32-wasip1 -- --nocapture` now builds the wasm binary; execution still fails under Wasmtime because Workers headers rely on wasm-bindgen imports unavailable in this runtime, which matches prior expectations. + +## Review (2025-09-20 23:10 UTC) +- Added `#![cfg_attr(target_arch = "wasm32", no_main)]` and imported `anyedge_core::response::IntoResponse` so the Cloudflare demo binary compiles to wasm without missing entrypoint errors; error handling now converts `EdgeError` via `into_response`. +- Cleaned up the Cloudflare adapter’s stale `Write` import and set the demo crate to depend on `anyedge-core` explicitly. +- `cargo build -p app-demo-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown` completes successfully (only standard warnings remain). + ## Review (2025-09-20 23:25 UTC) - `anyedge_adapter_cloudflare::dispatch` now returns `worker::Result` after converting internal `EdgeError`s to `worker::Error`, eliminating the need for a separate helper. - The Cloudflare demo entrypoint matches the Fastly style: build the app, init the logger, and await `dispatch`. - `cargo build -p app-demo-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown` stays green (standard brotli warning only). - Updated CLI templates so newly scaffolded apps use `anyedge_adapter_fastly::dispatch` / `anyedge_adapter_cloudflare::dispatch` with logger init, matching the demos. + +## Current Task (expand_action_impl coverage + cleanup) +- [x] Audit `expand_action_impl` behaviour to list any untested code paths or edge cases (e.g., tuple destructuring errors, non-RC tuple structs, extractor invocation). +- [x] Add focused tests in `crates/anyedge-macros/src/action.rs` to cover the missing scenarios while keeping contract unchanged. +- [x] Simplify the implementation if warranted (e.g., helper extraction, clearer error handling) without altering observable behaviour; highlight the deltas in the review section. +- [x] Run `cargo test` workspace-wide and note results. +- [x] Record a new review entry summarising the changes, assumptions, and outstanding items. + +## Review (2025-11-07 17:52:45 UTC) +- Summary: Extracted RequestContext pattern normalisation into a helper for clearer error aggregation and broadened the macro tests to cover attribute arguments, self receivers, tuple binding mistakes, and extractor codegen so `expand_action_impl` remains well-specified. +- Assumptions: String-matching the generated `FromRequest` call stays stable because we don't plan to rename that trait or method; tuple destructuring for RequestContext will continue to expect a single binding. +- Outstanding: None; `cargo test` (workspace) succeeded after the new tests. + +## Current Task (template proxy_demo parity) +- [x] Update `crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs` so the generated `proxy_demo` matches the example handler (`#[action]` + `RequestContext(ctx): RequestContext` binding). +- [x] Run `cargo test` to ensure the template change doesn’t break the workspace. +- [x] Capture a review entry summarising the template update and any follow-ups. + +## Review (2025-11-07 17:55:17 UTC) +- Summary: Aligned the CLI template’s `proxy_demo` definition with the app demo (now tagged with `#[action]` and destructuring `RequestContext`) so generated projects inherit the same extractor ergonomics. +- Assumptions: Template consumers expect the proxy route to behave like the example app; no additional template files reference the old signature. +- Outstanding: None; `cargo test` across the workspace passed after the template tweak. + +## Current Task (RequestContext pattern support) +- [x] Teach the `#[action]` macro to accept tuple-struct style parameters like `RequestContext(ctx): RequestContext` by normalising that pattern to the owned context argument (ensure the same ownership semantics and keep duplicate checks). +- [x] Update the `proxy_demo` handler in `examples/app-demo/crates/app-demo-core/src/handlers.rs` to demonstrate the new binding style. +- [x] Run `cargo test` for the workspace and fix any regressions. +- [x] Append a new review entry (summary, assumptions, outstanding items) once the change is complete. + +## Review (2025-11-07 17:48:52 UTC) +- Summary: Normalised `RequestContext` parameters passed through `#[action]` so tuple-style bindings (e.g. `RequestContext(ctx): RequestContext`) collapse to the owned context, added regression tests covering the pattern, and showcased the syntax on `proxy_demo`. +- Assumptions: Only one owned `RequestContext` parameter should exist per handler; tuple-style bindings only contain a single pattern element. +- Outstanding: None; `cargo test` passed for the entire workspace (no warnings after the final iteration). + +## Review (2025-11-07 17:39:28 UTC) +- Summary: Extended `#[action]` to accept a single `RequestContext` parameter (with duplicate detection and helper tests) and applied the attribute to `proxy_demo`, relying on the original handler logic. +- Assumptions: `RequestContext` parameters are owned values (no reference variants needed) and only one is expected per handler. +- Outstanding: None; `cargo test` across the workspace passed after the macro test adjustment.