diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 1ecfb95..fcf4c93 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,4 +1,4 @@ -# To get started with Dependabot version updates, you'll need to specify whichhttps://github.com/stackpop/anyedge/tree/main +# To get started with Dependabot version updates, you'll need to specify whichhttps://github.com/stackpop/edgezero/tree/main # package ecosystems to update and where the package manifests are located. # Please see the documentation for all configuration options: # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file diff --git a/AGENTS.md b/AGENTS.md index d8c5e8c..7b124a9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,25 +1,28 @@ # Agent Notes This repository is currently tended by an automated assistant (Codex) that helps -craft the AnyEdge workspace. A few conventions are worth remembering when the +craft the EdgeZero workspace. A few conventions are worth remembering when the agent is asked to make additional changes: ## Standard Workflow + 1. First think through the problem, read the codebase for relevant files, and write a plan to the file: TODO.md. If the TODO.md file does not yet exist, go ahead and create it. 2. The plan should have a list of todo items that you can check off as you complete them 3. Before you begin working, show me the full plan of the work to be done and get my approval before commencing any coding work 4. Then, begin working on the todo items, marking them as complete as you go. 5. As you complete each todo item, give me a high level explanation of what changes you made 6. If you cannot complete a todo, mark it as blocked in TODO.md and explain why. -7. Make every task and code change you do as simple as possible. We want to avoid making any massive or complex changes. Every change should impact as little code as possible. +7. Make every task and code change you do as simple as possible. We want to avoid making any massive or complex changes. Every change should impact as little code as possible. 8. Finally, add a review section to the TODO.md file with a summary of the changes you made, assumptions made, any unresolved issues or errors you couldn't fix, and any other relevant information. Add the date and time showing when the job was finished. ## Tools ### Context7 MCP + - Use Context7 MCP to supplement local codebase knowledge with up-to-date library documentation and coding examples ### Playwright MCP + - use the Playwright MCP in order to check and validate any user interface changes you make - you can also use this MCP to check the web browser console for any error messages which may come up - iterate up to a maximum of 5 times for any one particular feature; an iteration = one cycle of code change + Playwright re-run @@ -27,44 +30,54 @@ agent is asked to make additional changes: - Save any failing test cases or console errors in a debug.md file so we can review them together. ## Testing + always run `cargo test` after touching code. Individual crates - can be scoped via `cargo test -p ` when a partial run is faster. +can be scoped via `cargo test -p ` when a partial run is faster. + ## Routing syntax + route definitions must use matchit 0.8 style - parameters (`/resource/{id}` or `/static/{*rest}`); we intentionally do not - support legacy `:id` syntax. +parameters (`/resource/{id}` or `/static/{*rest}`); we intentionally do not +support legacy `:id` syntax. + ## Adapters – Fastly and Cloudflare adapters expose request context helpers - in `context.rs` and translation helpers in `request.rs` / `response.rs`. - Tests for adapter behaviour live beside those modules. + +in `context.rs` and translation helpers in `request.rs` / `response.rs`. +Tests for adapter behaviour live beside those modules. ## Examples + the demo crates under `examples/app-demo/` share router - logic via `app-demo-core`. Local smoke testing flows through - `cargo run -p anyedge-cli --features dev-example -- dev`, which serves the demo - router on http://127.0.0.1:8787. Build provider targets with - `app-demo-adapter-fastly` / `app-demo-adapter-cloudflare` when you need Fastly - or Cloudflare binaries. +logic via `app-demo-core`. Local smoke testing flows through +`cargo run -p edgezero-cli --features dev-example -- dev`, which serves the demo +router on http://127.0.0.1:8787. Build provider targets with +`app-demo-adapter-fastly` / `app-demo-adapter-cloudflare` when you need Fastly +or Cloudflare binaries. ## Style– prefer colocating tests with implementation modules, favour + async/await-friendly code that compiles to Wasm, and avoid runtime-specific dependencies like Tokio. -- Use the HTTP aliases exported from `anyedge_core` (`Method`, `StatusCode`, + +- Use the HTTP aliases exported from `edgezero_core` (`Method`, `StatusCode`, `HeaderMap`, etc.) instead of importing types directly from the `http` crate. -- Prefer the `#[anyedge_core::action]` macro for new handlers so extractor +- Prefer the `#[edgezero_core::action]` macro for new handlers so extractor arguments (`Json`, `Query`, `ValidatedJson`, etc.) stay declarative. - Extractors live under `anyedge_core::` and integrate with the `validator` + Extractors live under `edgezero_core::` and integrate with the `validator` crate for `Validated*` variants. ## Logging -- Platform logging helpers live in the adapters: use `anyedge_adapter_fastly::init_logger()` / `anyedge_adapter_cloudflare::init_logger()` and + +- Platform logging helpers live in the adapters: use `edgezero_adapter_fastly::init_logger()` / `edgezero_adapter_cloudflare::init_logger()` and fall back to something like `simple_logger` for local builds. ## Proxy helpers -- Use `anyedge_core::proxy::ProxyService` with the adapter clients - (`anyedge_adapter_fastly::FastlyProxyClient`, `anyedge_adapter_cloudflare::CloudflareProxyClient`) + +- Use `edgezero_core::proxy::ProxyService` with the adapter clients + (`edgezero_adapter_fastly::FastlyProxyClient`, `edgezero_adapter_cloudflare::CloudflareProxyClient`) when wiring proxy routes so streaming and compression handling stay consistent. - Keep synthetic local proxy behaviour lightweight so examples can run without - Fastly/Cloudflare credentials; rely on the proxy test clients in `anyedge-core` for unit coverage. + Fastly/Cloudflare credentials; rely on the proxy test clients in `edgezero-core` for unit coverage. When in doubt, keep changes minimal, document behaviour in `README.md`, and ensure the workspace stays Wasm-friendly. diff --git a/Cargo.lock b/Cargo.lock index 32c02bc..8c028f5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -91,145 +91,6 @@ dependencies = [ "windows-sys 0.60.2", ] -[[package]] -name = "anyedge-adapter" -version = "0.1.0" -dependencies = [ - "once_cell", - "tempfile", - "toml", -] - -[[package]] -name = "anyedge-adapter-axum" -version = "0.1.0" -dependencies = [ - "anyedge-adapter", - "anyedge-core", - "anyhow", - "async-trait", - "axum", - "bytes", - "ctor", - "futures", - "futures-util", - "http", - "log", - "reqwest", - "simple_logger", - "tempfile", - "thiserror 2.0.17", - "tokio", - "toml", - "tower", - "tracing", - "walkdir", -] - -[[package]] -name = "anyedge-adapter-cloudflare" -version = "0.1.0" -dependencies = [ - "anyedge-adapter", - "anyedge-core", - "async-trait", - "brotli", - "bytes", - "ctor", - "flate2", - "futures", - "futures-util", - "log", - "walkdir", - "wasm-bindgen-test", - "web-sys", - "worker", -] - -[[package]] -name = "anyedge-adapter-fastly" -version = "0.1.0" -dependencies = [ - "anyedge-adapter", - "anyedge-core", - "async-stream", - "async-trait", - "brotli", - "bytes", - "chrono", - "ctor", - "fastly", - "fern", - "flate2", - "futures", - "futures-util", - "log", - "log-fastly", - "tempfile", - "walkdir", -] - -[[package]] -name = "anyedge-cli" -version = "0.1.0" -dependencies = [ - "anyedge-adapter", - "anyedge-adapter-axum", - "anyedge-adapter-cloudflare", - "anyedge-adapter-fastly", - "anyedge-core", - "app-demo-core", - "clap", - "futures", - "handlebars", - "log", - "serde", - "serde_json", - "tempfile", - "toml", -] - -[[package]] -name = "anyedge-core" -version = "0.1.0" -dependencies = [ - "anyedge-macros", - "anyhow", - "async-compression", - "async-stream", - "async-trait", - "brotli", - "bytes", - "flate2", - "futures", - "futures-util", - "http", - "http-body", - "log", - "matchit 0.9.0", - "serde", - "serde_json", - "serde_urlencoded", - "thiserror 2.0.17", - "toml", - "tower-service", - "tracing", - "validator", -] - -[[package]] -name = "anyedge-macros" -version = "0.1.0" -dependencies = [ - "log", - "proc-macro2", - "quote", - "serde", - "syn 2.0.108", - "toml", - "validator", -] - [[package]] name = "anyhow" version = "1.0.100" @@ -240,11 +101,11 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" name = "app-demo-adapter-axum" version = "0.1.0" dependencies = [ - "anyedge-adapter-axum", - "anyedge-core", "anyhow", "app-demo-core", "axum", + "edgezero-adapter-axum", + "edgezero-core", "log", "simple_logger", "tokio", @@ -255,9 +116,9 @@ dependencies = [ name = "app-demo-adapter-cloudflare" version = "0.1.0" dependencies = [ - "anyedge-adapter-cloudflare", - "anyedge-core", "app-demo-core", + "edgezero-adapter-cloudflare", + "edgezero-core", "worker", ] @@ -265,9 +126,9 @@ dependencies = [ name = "app-demo-adapter-fastly" version = "0.1.0" dependencies = [ - "anyedge-adapter-fastly", - "anyedge-core", "app-demo-core", + "edgezero-adapter-fastly", + "edgezero-core", "fastly", "log", "once_cell", @@ -277,9 +138,9 @@ dependencies = [ name = "app-demo-core" version = "0.1.0" dependencies = [ - "anyedge-core", "async-trait", "bytes", + "edgezero-core", "futures", "serde", "serde_json", @@ -761,6 +622,145 @@ version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f678cf4a922c215c63e0de95eb1ff08a958a81d47e485cf9da1e27bf6305cfa5" +[[package]] +name = "edgezero-adapter" +version = "0.1.0" +dependencies = [ + "once_cell", + "tempfile", + "toml", +] + +[[package]] +name = "edgezero-adapter-axum" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "axum", + "bytes", + "ctor", + "edgezero-adapter", + "edgezero-core", + "futures", + "futures-util", + "http", + "log", + "reqwest", + "simple_logger", + "tempfile", + "thiserror 2.0.17", + "tokio", + "toml", + "tower", + "tracing", + "walkdir", +] + +[[package]] +name = "edgezero-adapter-cloudflare" +version = "0.1.0" +dependencies = [ + "async-trait", + "brotli", + "bytes", + "ctor", + "edgezero-adapter", + "edgezero-core", + "flate2", + "futures", + "futures-util", + "log", + "walkdir", + "wasm-bindgen-test", + "web-sys", + "worker", +] + +[[package]] +name = "edgezero-adapter-fastly" +version = "0.1.0" +dependencies = [ + "async-stream", + "async-trait", + "brotli", + "bytes", + "chrono", + "ctor", + "edgezero-adapter", + "edgezero-core", + "fastly", + "fern", + "flate2", + "futures", + "futures-util", + "log", + "log-fastly", + "tempfile", + "walkdir", +] + +[[package]] +name = "edgezero-cli" +version = "0.1.0" +dependencies = [ + "app-demo-core", + "clap", + "edgezero-adapter", + "edgezero-adapter-axum", + "edgezero-adapter-cloudflare", + "edgezero-adapter-fastly", + "edgezero-core", + "futures", + "handlebars", + "log", + "serde", + "serde_json", + "tempfile", + "toml", +] + +[[package]] +name = "edgezero-core" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-compression", + "async-stream", + "async-trait", + "brotli", + "bytes", + "edgezero-macros", + "flate2", + "futures", + "futures-util", + "http", + "http-body", + "log", + "matchit 0.9.0", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 2.0.17", + "toml", + "tower-service", + "tracing", + "validator", +] + +[[package]] +name = "edgezero-macros" +version = "0.1.0" +dependencies = [ + "log", + "proc-macro2", + "quote", + "serde", + "syn 2.0.108", + "toml", + "validator", +] + [[package]] name = "either" version = "1.15.0" diff --git a/Cargo.toml b/Cargo.toml index 9b9f845..107a8d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,12 +1,12 @@ [workspace] members = [ - "crates/anyedge-adapter-axum", - "crates/anyedge-adapter-cloudflare", - "crates/anyedge-adapter-fastly", - "crates/anyedge-adapter", - "crates/anyedge-cli", - "crates/anyedge-core", - "crates/anyedge-macros", + "crates/edgezero-adapter-axum", + "crates/edgezero-adapter-cloudflare", + "crates/edgezero-adapter-fastly", + "crates/edgezero-adapter", + "crates/edgezero-cli", + "crates/edgezero-core", + "crates/edgezero-macros", "examples/app-demo/crates/app-demo-adapter-cloudflare", "examples/app-demo/crates/app-demo-adapter-axum", "examples/app-demo/crates/app-demo-core", @@ -17,15 +17,15 @@ resolver = "2" [workspace.package] edition = "2021" version = "0.1.0" -authors = ["AnyEdge Team "] +authors = ["EdgeZero Team "] license = "Apache-2.0" [workspace.dependencies] -anyedge-adapter-axum = { path = "crates/anyedge-adapter-axum", default-features = false } -anyedge-adapter-cloudflare = { path = "crates/anyedge-adapter-cloudflare", default-features = false } -anyedge-adapter-fastly = { path = "crates/anyedge-adapter-fastly", default-features = false } -anyedge-adapter = { path = "crates/anyedge-adapter" } -anyedge-core = { path = "crates/anyedge-core", default-features = false } +edgezero-adapter-axum = { path = "crates/edgezero-adapter-axum", default-features = false } +edgezero-adapter-cloudflare = { path = "crates/edgezero-adapter-cloudflare", default-features = false } +edgezero-adapter-fastly = { path = "crates/edgezero-adapter-fastly", default-features = false } +edgezero-adapter = { path = "crates/edgezero-adapter" } +edgezero-core = { path = "crates/edgezero-core", default-features = false } anyhow = "1" app-demo-core = { path = "examples/app-demo/crates/app-demo-core" } async-compression = { version = "0.4", features = ["futures-io", "gzip", "brotli"] } diff --git a/README.md b/README.md index 10c4846..459d56f 100644 --- a/README.md +++ b/README.md @@ -1,32 +1,32 @@ -# AnyEdge +# EdgeZero -AnyEdge is a production-ready toolkit for writing an HTTP workload once and +EdgeZero is a production-ready toolkit for writing an HTTP workload once and deploying it across multiple edge providers. The core stays runtime-agnostic so it compiles cleanly to WebAssembly targets (Fastly Compute@Edge, Cloudflare Workers) and to native hosts (Axum/Tokio) without code changes. ## Workspace layout -- `crates/anyedge-core` - routing, request/response primitives, middleware chaining, extractor utilities built on `http`, `tower::Service`, and `matchit` 0.8. Handlers opt into extractors such as `Json`, `Path`, and `ValidatedQuery`, and the crate re-exports HTTP types (`Method`, `StatusCode`, `HeaderMap`, ...). -- `crates/anyedge-macros` - procedural macros that power `#[anyedge_core::action]` and related derive helpers. -- `crates/anyedge-adapter-fastly` - Fastly Compute@Edge bridge that maps Fastly request/response types into the shared model and exposes `FastlyRequestContext` plus logging conveniences. -- `crates/anyedge-adapter-cloudflare` - Cloudflare Workers bridge providing `CloudflareRequestContext` and logger bootstrap helpers. -- `crates/anyedge-adapter-axum` - host-side adapter that wraps `RouterService` in Axum/Tokio services for local development and native deployments (the dev server now runs through this crate). -- `crates/anyedge-cli` - CLI for project scaffolding, the local dev server, and adapter-aware build/deploy helpers. Ships with an optional demo dependency. +- `crates/edgezero-core` - routing, request/response primitives, middleware chaining, extractor utilities built on `http`, `tower::Service`, and `matchit` 0.8. Handlers opt into extractors such as `Json`, `Path`, and `ValidatedQuery`, and the crate re-exports HTTP types (`Method`, `StatusCode`, `HeaderMap`, ...). +- `crates/edgezero-macros` - procedural macros that power `#[edgezero_core::action]` and related derive helpers. +- `crates/edgezero-adapter-fastly` - Fastly Compute@Edge bridge that maps Fastly request/response types into the shared model and exposes `FastlyRequestContext` plus logging conveniences. +- `crates/edgezero-adapter-cloudflare` - Cloudflare Workers bridge providing `CloudflareRequestContext` and logger bootstrap helpers. +- `crates/edgezero-adapter-axum` - host-side adapter that wraps `RouterService` in Axum/Tokio services for local development and native deployments (the dev server now runs through this crate). +- `crates/edgezero-cli` - CLI for project scaffolding, the local dev server, and adapter-aware build/deploy helpers. Ships with an optional demo dependency. - `examples/app-demo` - reference application built on the shared router. Includes `crates/app-demo-core` (routes), `crates/app-demo-adapter-fastly` (Fastly binary + `fastly.toml`), `crates/app-demo-adapter-cloudflare` (Workers entrypoint + `wrangler.toml`), and `crates/app-demo-adapter-axum` (native dev server). ## Quick start ```bash # Install the CLI (from this workspace or a published crate) -cargo install --path crates/anyedge-cli +cargo install --path crates/edgezero-cli -# Scaffold a new AnyEdge app targeting Fastly, Cloudflare, and Axum -anyedge new my-app --adapters fastly cloudflare axum +# Scaffold a new EdgeZero app targeting Fastly, Cloudflare, and Axum +edgezero new my-app --adapters fastly cloudflare axum cd my-app # Start the local Axum-powered dev server -anyedge dev +edgezero dev # Hit one of the generated endpoints curl http://127.0.0.1:8787/echo/alice @@ -35,7 +35,7 @@ curl http://127.0.0.1:8787/echo/alice cargo test # Optional: explore the demo project bundled with this repo -cargo run -p anyedge-cli --features dev-example -- dev +cargo run -p edgezero-cli --features dev-example -- dev ``` To run the demo router from `examples/app-demo`, enable the optional @@ -51,12 +51,12 @@ The demo routes showcase core features: - `POST /echo` - JSON extractor + response builder. - `/info` - shared state injection. -Handlers stay concise by using the `#[action]` macro re-exported from `anyedge-core`: +Handlers stay concise by using the `#[action]` macro re-exported from `edgezero-core`: ```rust -use anyedge_core::action; -use anyedge_core::extractor::Json; -use anyedge_core::response::Text; +use edgezero_core::action; +use edgezero_core::extractor::Json; +use edgezero_core::response::Text; #[derive(serde::Deserialize)] struct EchoBody { @@ -71,38 +71,38 @@ async fn echo_json(Json(body): Json) -> Text { ## CLI tooling -The CLI and adapters now expect an `anyedge.toml` manifest alongside your workspace. The manifest +The CLI and adapters now expect an `edgezero.toml` manifest alongside your workspace. The manifest describes the shared app (entry crate, optional middleware list, routes, adapters, and logging) so Fastly/Cloudflare binaries, the CLI, and any local tooling all agree on configuration. The demo -manifest lives in `examples/app-demo/anyedge.toml`, and the scaffolder emits the same structure for +manifest lives in `examples/app-demo/edgezero.toml`, and the scaffolder emits the same structure for new projects. -The `anyedge-cli` crate produces the `anyedge` binary (enabled by the `cli` feature). Run it locally with `cargo run -p anyedge-cli -- `. Key subcommands: +The `edgezero-cli` crate produces the `edgezero` binary (enabled by the `cli` feature). Run it locally with `cargo run -p edgezero-cli -- `. Key subcommands: -- `anyedge new` - scaffolds a fully wired workspace (pass `--adapters` to pick your targets). -- `anyedge dev` - starts the local Axum HTTP server using the current project's manifest (pass `--features dev-example` when running from this repository to boot the demo app). -- `anyedge build --adapter fastly` - builds the Fastly example to `wasm32-wasip1` and copies the artifact into `anyedge/pkg/`. -- `anyedge serve --adapter fastly` - shells out to `fastly compute serve` after locating the Fastly manifest. -- `anyedge deploy --adapter fastly` - wraps `fastly compute deploy`. -- `anyedge build --adapter axum` - builds your native entrypoint (useful for containers or local integration tests). -- `anyedge serve --adapter axum` - runs the generated Axum entrypoint with `cargo run`, ideal for local or containerised development. +- `edgezero new` - scaffolds a fully wired workspace (pass `--adapters` to pick your targets). +- `edgezero dev` - starts the local Axum HTTP server using the current project's manifest (pass `--features dev-example` when running from this repository to boot the demo app). +- `edgezero build --adapter fastly` - builds the Fastly example to `wasm32-wasip1` and copies the artifact into `edgezero/pkg/`. +- `edgezero serve --adapter fastly` - shells out to `fastly compute serve` after locating the Fastly manifest. +- `edgezero deploy --adapter fastly` - wraps `fastly compute deploy`. +- `edgezero build --adapter axum` - builds your native entrypoint (useful for containers or local integration tests). +- `edgezero serve --adapter axum` - runs the generated Axum entrypoint with `cargo run`, ideal for local or containerised development. -Adapters register themselves lazily through their `anyedge_adapter_*::cli` modules. With the Axum adapter available you can generate, serve, and test a native host target without leaving the workspace. +Adapters register themselves lazily through their `edgezero_adapter_*::cli` modules. With the Axum adapter available you can generate, serve, and test a native host target without leaving the workspace. ## Logging -`anyedge-core` relies on the standard `log` facade. Platform adapters expose helper +`edgezero-core` relies on the standard `log` facade. Platform adapters expose helper functions so you can install the right backend when your app boots: -- Fastly: call `anyedge_adapter_fastly::init_logger()` (wraps `log_fastly`). -- Cloudflare Workers: call `anyedge_adapter_cloudflare::init_logger()` (logs via +- Fastly: call `edgezero_adapter_fastly::init_logger()` (wraps `log_fastly`). +- Cloudflare Workers: call `edgezero_adapter_cloudflare::init_logger()` (logs via Workers `console_log!`). -- Axum/native: install a standard logger (`simple_logger`, `tracing-subscriber`, etc.) before booting `anyedge_adapter_axum::AxumDevServer`. +- Axum/native: install a standard logger (`simple_logger`, `tracing-subscriber`, etc.) before booting `edgezero_adapter_axum::AxumDevServer`. - Other targets: initialise a fallback logger such as `simple_logger` before building your app. -The helper `run_app::(include_str!("path/to/anyedge.toml"), req)` in -`anyedge-adapter-fastly` and the Cloudflare equivalent encapsulate manifest loading and logger +The helper `run_app::(include_str!("path/to/edgezero.toml"), req)` in +`edgezero-adapter-fastly` and the Cloudflare equivalent encapsulate manifest loading and logger initialisation, so the adapters you scaffold only need to call the helper from `main`. ## Provider builds @@ -111,20 +111,20 @@ Fastly Compute@Edge (requires the `fastly` CLI and the `wasm32-wasip1` target): ```bash rustup target add wasm32-wasip1 -cd anyedge/examples/app-demo +cd edgezero/examples/app-demo cargo build -p app-demo-adapter-fastly --target wasm32-wasip1 --features fastly # or from the workspace root: -cargo run -p anyedge-cli -- build --adapter fastly -cargo run -p anyedge-cli -- serve --adapter fastly +cargo run -p edgezero-cli -- build --adapter fastly +cargo run -p edgezero-cli -- serve --adapter fastly ``` -The CLI helpers locate `fastly.toml`, build the Wasm artifact, place it in `anyedge/pkg/`, and run `fastly compute serve` from `examples/app-demo/crates/app-demo-adapter-fastly`. +The CLI helpers locate `fastly.toml`, build the Wasm artifact, place it in `edgezero/pkg/`, and run `fastly compute serve` from `examples/app-demo/crates/app-demo-adapter-fastly`. Cloudflare Workers (requires `wrangler` and the `wasm32-unknown-unknown` target): ```bash rustup target add wasm32-unknown-unknown -cd anyedge/examples/app-demo +cd edgezero/examples/app-demo cargo build -p app-demo-adapter-cloudflare --target wasm32-unknown-unknown wrangler dev --config crates/app-demo-adapter-cloudflare/wrangler.toml ``` @@ -133,15 +133,15 @@ Axum / native hosts: ```bash # Build or run using the scaffolded commands -anyedge build --adapter axum -anyedge serve --adapter axum +edgezero build --adapter axum +edgezero serve --adapter axum ``` -The Fastly and Cloudflare adapters translate provider request/response shapes into the shared `anyedge-core` model and stash provider metadata in the request extensions so handlers can reach runtime-specific APIs. +The Fastly and Cloudflare adapters translate provider request/response shapes into the shared `edgezero-core` model and stash provider metadata in the request extensions so handlers can reach runtime-specific APIs. ## Path parameters -`anyedge-core` uses matchit 0.8+. Define parameters with `{name}` segments +`edgezero-core` uses matchit 0.8+. Define parameters with `{name}` segments (`/blog/{slug}`) and catch-alls with `{*rest}`. Legacy Axum-style `:name` segments are intentionally unsupported. @@ -149,7 +149,7 @@ segments are intentionally unsupported. Enable `RouterBuilder::enable_route_listing()` when you want a quick view of the registered routes. It injects a JSON endpoint at -`DEFAULT_ROUTE_LISTING_PATH` (defaults to `/__anyedge/routes`) that returns an +`DEFAULT_ROUTE_LISTING_PATH` (defaults to `/__edgezero/routes`) that returns an array of `{ "method": "GET", "path": "/..." }` entries for every handler. Use `RouterBuilder::enable_route_listing_at("/debug/routes")` to expose the listing at a custom path. @@ -165,23 +165,23 @@ payload before sending it downstream. ## Proxying upstream services -`anyedge-core` ships with `ProxyRequest`, `ProxyResponse`, and the `ProxyService` wrapper so edge adapters can forward traffic while reusing the same handler logic: +`edgezero-core` ships with `ProxyRequest`, `ProxyResponse`, and the `ProxyService` wrapper so edge adapters can forward traffic while reusing the same handler logic: ```rust -use anyedge_core::http::Uri; -use anyedge_core::proxy::{ProxyRequest, ProxyService}; +use edgezero_core::http::Uri; +use edgezero_core::proxy::{ProxyRequest, ProxyService}; let target: Uri = "https://example.com/api".parse()?; let proxy_request = ProxyRequest::from_request(request, target); let response = ProxyService::new(client).forward(proxy_request).await?; ``` -Use the adapter-specific clients (`anyedge_adapter_fastly::FastlyProxyClient` and `anyedge_adapter_cloudflare::CloudflareProxyClient`) when compiling for those adapters, and swap in lightweight test clients during unit tests. The proxy helpers preserve streaming bodies and transparently decode gzip or brotli payloads before they reach your handler. +Use the adapter-specific clients (`edgezero_adapter_fastly::FastlyProxyClient` and `edgezero_adapter_cloudflare::CloudflareProxyClient`) when compiling for those adapters, and swap in lightweight test clients during unit tests. The proxy helpers preserve streaming bodies and transparently decode gzip or brotli payloads before they reach your handler. ## Testing Unit tests live next to the modules they exercise. Run the entire suite with -`cargo test`, or scope to a single crate via `cargo test -p anyedge-core`. +`cargo test`, or scope to a single crate via `cargo test -p edgezero-core`. The adapter crates include lightweight host-side tests that validate context insertion and URI parsing without needing the Wasm toolchains. @@ -204,8 +204,8 @@ Tell Cargo to use Wasmtime when running the wasm tests: ```bash export CARGO_TARGET_WASM32_WASIP1_RUNNER="wasmtime run --dir=." -cargo test -p anyedge-adapter-fastly --features fastly --target wasm32-wasip1 +cargo test -p edgezero-adapter-fastly --features fastly --target wasm32-wasip1 ``` -Streaming responses are covered in the `anyedge-core` router tests and in the +Streaming responses are covered in the `edgezero-core` router tests and in the Fastly adapter tests to ensure chunked bodies make it to the provider output. diff --git a/TODO.md b/TODO.md index 40e0780..700e47b 100644 --- a/TODO.md +++ b/TODO.md @@ -1,62 +1,67 @@ -# AnyEdge TODO +# EdgeZero TODO High-level backlog and decisions to drive the next milestones. ## Queue (near-term) ### High Priority + - [ ] 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 - [ ] Core proxy: add async fetch facade (feature `async-client`) and implement Cloudflare proxy async fetch facade (feature `async-client`) and implement Cloudflare proxy ### Medium Priority + - [ ] Fastly demo: add optional backend example to validate `req.send("backend")` - [ ] Core: utility to serve embedded static files via `include_str!`/`include_bytes!` with proper Content-Type and HEAD (no body) handling - [ ] Docs: document header/method/status mapping to `http` crate - [ ] Docs: add RouteOptions + streaming policy section (examples done; expand README section) ### Completed / Ongoing Maintenance -- [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] CLI: manifest-driven `edgezero build --adapter fastly|cloudflare|axum` wiring via `crates/edgezero-cli/src/main.rs` + adapter manifests. +- [x] CLI: manifest-driven `edgezero 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 -- [x] Controllers: add `anyedge-controller` + `anyedge-macros` with typed extractors and `#[action]` helpers +- [x] Controllers: add `edgezero-controller` + `edgezero-macros` with typed extractors and `#[action]` helpers ## Test Coverage Plan (2025-09-18) + - [ ] Adapters: introduce Fastly/Cloudflare mapping tests (headers, streaming, proxy failure) to catch glue regressions. - [ ] Adapters: assert error-path mapping for Fastly/Cloudflare request conversion and re-enable the ignored Cloudflare response header test. -- [ ] CLI: add integration tests for `anyedge new` scaffolding, feature-flag builds, and `dev` fallback app. +- [ ] CLI: add integration tests for `edgezero new` scaffolding, feature-flag builds, and `dev` fallback app. - [ ] CLI: cover `dev_server`, generator, and template scaffolding flows with tempdir-based integration tests to guard manual HTTP parsing and shell commands. - [ ] CI: verify feature combinations (without `dev-example`, `json`, `form`) compile and run basic smoke tests. - [ ] Macros: add trybuild coverage for `app!` manifest expansion (route/middleware generation and error surfacing). -- [x] Core: unit-test `App::build_app`/`Hooks` wiring and `PathParams::deserialize` edge cases beyond indirect coverage. *(Added targeted unit tests in `crates/anyedge-core/src/app.rs` and `crates/anyedge-core/src/params.rs`.)* -- [x] Coverage hygiene: consolidate duplicate router/extractor request-parsing tests and share adapter contract fixtures to reduce redundant maintenance. *(Router duplicates trimmed; extractor suite now owns request parsing checks.)* +- [x] Core: unit-test `App::build_app`/`Hooks` wiring and `PathParams::deserialize` edge cases beyond indirect coverage. _(Added targeted unit tests in `crates/edgezero-core/src/app.rs` and `crates/edgezero-core/src/params.rs`.)_ +- [x] Coverage hygiene: consolidate duplicate router/extractor request-parsing tests and share adapter contract fixtures to reduce redundant maintenance. _(Router duplicates trimmed; extractor suite now owns request parsing checks.)_ - [x] Router: add regression cases for overlapping routes, prefix/nest behaviour, and BodyMode error handling (`Streaming` vs `Buffered`). - [x] Controller: cover negative paths (`State` missing, `ValidatedJson` errors) and assert returned status/body. ## Milestones + - [x] Fastly adapter MVP - - [x] Map Fastly Request -> `anyedge-core::Request` - - [x] Map `anyedge-core::Response` -> Fastly Response (headers/body) + - [x] Map Fastly Request -> `edgezero-core::Request` + - [x] Map `edgezero-core::Response` -> Fastly Response (headers/body) - [x] Handle binary/text bodies and content-length - [x] Example: runnable Fastly demo (`examples/app-demo/crates/app-demo-adapter-fastly`) with wasm32-wasip1 target and explicit logger init - [x] Streaming: native streaming on Fastly via `stream_to_client` (wasm32-wasip1), buffered fallback elsewhere - [ ] Cloudflare Workers adapter MVP - - [x] Basic mapping: Workers Request -> AnyEdge Request - - [x] Basic mapping: AnyEdge Response -> Workers Response (buffered bodies) + - [x] Basic mapping: Workers Request -> EdgeZero Request + - [x] Basic mapping: EdgeZero Response -> Workers Response (buffered bodies) - [ ] Streaming behavior (ReadableStream) and backpressure - [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()`) - - [x] `anyedge build --adapter fastly|cloudflare` - - [x] `anyedge deploy --adapter fastly|cloudflare` - - [ ] `anyedge dev` improvements: better HTTP parsing, hot-reload + - [x] `edgezero new `: scaffold an app (lib with `build_app()`) + - [x] `edgezero build --adapter fastly|cloudflare` + - [x] `edgezero deploy --adapter fastly|cloudflare` + - [ ] `edgezero dev` improvements: better HTTP parsing, hot-reload - [x] Config - - [x] `anyedge.toml`: app name, routes, provider-specific settings + - [x] `edgezero.toml`: app name, routes, provider-specific settings - [x] Secrets/ENV strategy and provider bindings - [ ] Observability - [ ] Logging levels; feature-gated tracing @@ -78,12 +83,14 @@ High-level backlog and decisions to drive the next milestones. - [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`) + +- [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/edgezero-adapter-fastly/tests/contract.rs`, Cloudflare contract tests under `crates/edgezero-adapter-cloudflare/tests/contract.rs`, manifest schema in `docs/manifest.md`) - [ ] Provider additions: prototype a third adapter (e.g. AWS Lambda@Edge or Vercel Edge Functions) using the stabilized adapter API to validate cross-provider abstractions. -- [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. +- [x] Manifest ergonomics: design an `edgezero.toml` schema that mirrors Spin’s manifest convenience (route triggers, env/secrets, build targets) while remaining provider-agnostic; update CLI scaffolding accordingly. (`crates/edgezero-cli/src/manifest.rs`, templates in `crates/edgezero-cli/src/templates/root/edgezero.toml.hbs`, doc `docs/manifest.md`, app-demo manifest `examples/app-demo/edgezero.toml`) +- [ ] Tooling parity: extend `edgezero-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? @@ -97,233 +104,276 @@ High-level backlog and decisions to drive the next milestones. ## 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. -- [x] Summarize findings on AnyEdge architecture, adapters, and tooling for the user's quick reference. +- [x] Summarize findings on EdgeZero architecture, adapters, and tooling for the user's quick reference. ### Familiarization Summary -- AnyEdge centres around `anyedge-core`, which provides provider-neutral HTTP primitives, routing, middleware, logging, and proxy abstractions; adapters reuse these types to stay DRY. -- Controller ergonomics live in `anyedge-controller` plus `anyedge-macros`, offering `#[action]` functions that extract typed inputs and return `Responder`s. -- Provider adapters (`anyedge-adapter-fastly`, `anyedge-adapter-cloudflare`) are feature-gated; each exposes `handle` plus logging/proxy helpers while delegating behaviour to the core crate. -- 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. + +- EdgeZero centres around `edgezero-core`, which provides provider-neutral HTTP primitives, routing, middleware, logging, and proxy abstractions; adapters reuse these types to stay DRY. +- Controller ergonomics live in `edgezero-controller` plus `edgezero-macros`, offering `#[action]` functions that extract typed inputs and return `Responder`s. +- Provider adapters (`edgezero-adapter-fastly`, `edgezero-adapter-cloudflare`) are feature-gated; each exposes `handle` plus logging/proxy helpers while delegating behaviour to the core crate. +- Supporting crates include `edgezero-std` for stdout logging, `edgezero-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. ## 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`. - [x] Add unit tests covering success and failure cases for the new extractors. - [x] Update public exports/docs to surface the new API and capture the change in this TODO review. ## Codex Plan (2025-09-18 - ValidateJson Alias) + - [x] Confirm existing JSON validation support and identify changes needed for `ValidateJson` ergonomics. - [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. - No outstanding issues or errors encountered; no code changes outside TODO.md updates. ## Review (2025-09-18 02:15 UTC) + - Introduced `ValidatedPath` and `ValidatedQuery` extractors leveraging `validator::Validate`, re-exported them, and broadened docs in `README.md`. -- Added targeted unit tests verifying both success and failure cases for validated path/query extraction; `cargo test -p anyedge-controller` passes. +- Added targeted unit tests verifying both success and failure cases for validated path/query extraction; `cargo test -p edgezero-controller` passes. - No additional assumptions beyond existing validation behaviour; no unresolved issues noted. ## 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. +- Cleaned README/TODO references accordingly and pruned alias-specific tests; `cargo test -p edgezero-controller` still passes. - Validator helpers now cover path, query, and JSON via `Validated*` types only. ## Review (2025-09-18 03:08 UTC) -- Implemented `anyedge build|deploy --adapter fastly` by wiring cargo wasm32 builds and Fastly CLI invocation in the CLI. -- Documented optional `dev-example` dependency in `anyedge-cli/README.md` and added error handling for unsupported adapters. -- Verified builds with `cargo test -p anyedge-cli`. + +- Implemented `edgezero build|deploy --adapter fastly` by wiring cargo wasm32 builds and Fastly CLI invocation in the CLI. +- Documented optional `dev-example` dependency in `edgezero-cli/README.md` and added error handling for unsupported adapters. +- Verified builds with `cargo test -p edgezero-cli`. ## Review (2025-09-18 03:27 UTC) -- Moved Fastly build/deploy/serve helpers into `anyedge-fastly` behind a `cli` feature and updated `anyedge-cli` to call through the provider abstraction. -- Improved Fastly manifest discovery to prefer the nearest crate manifest and added unit coverage for the new path logic. `cargo test -p anyedge-fastly --features cli`, `cargo test -p anyedge-cli`. + +- Moved Fastly build/deploy/serve helpers into `edgezero-fastly` behind a `cli` feature and updated `edgezero-cli` to call through the provider abstraction. +- Improved Fastly manifest discovery to prefer the nearest crate manifest and added unit coverage for the new path logic. `cargo test -p edgezero-fastly --features cli`, `cargo test -p edgezero-cli`. ## Codex Plan (2025-09-19 - Test Command Guidance) + - [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. -## 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.)* -- [ ] Implement minimal fix addressing the failure while staying within adapter boundaries. *(Blocked: `cargo test --features fastly --target wasm32-wasip1` currently fails under Viceroy with macOS keychain access errors.)* -- [ ] Re-run targeted tests (and any impacted suite) to confirm resolution. *(Blocked.)* -- [ ] Summarize work and outcomes in TODO review section with timestamp. *(Blocked.)* +## Codex Plan (2025-09-19 - Fix edgezero-fastly Tests) + +- [x] Reproduce `cargo test -p edgezero-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.)_ +- [ ] Implement minimal fix addressing the failure while staying within adapter boundaries. _(Blocked: `cargo test --features fastly --target wasm32-wasip1` currently fails under Viceroy with macOS keychain access errors.)_ +- [ ] Re-run targeted tests (and any impacted suite) to confirm resolution. _(Blocked.)_ +- [ ] Summarize work and outcomes in TODO review section with timestamp. _(Blocked.)_ ## Codex Plan (2025-09-19 - Comprehensive Test Runner) + - [x] Audit required commands for workspace + feature coverage including Fastly wasm build. - [x] Implement shell script to orchestrate the checks with Fastly-specific handling. - [x] Document script usage and outcomes in TODO review section with timestamp. ## 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. ## 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. ## 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. ## 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. ## 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. ## 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] Audit the app-demo crates to map controller-era APIs to the redesigned `edgezero-core` interfaces. - [x] Refactor `app-demo-core` handlers and routing to the new builder/extractor patterns, keeping streaming coverage intact. - [x] Update Fastly/Cloudflare entrypoints (and related metadata) so they compile against the redesigned core hooks. - [x] Run targeted tests for the app-demo crates and prepare review notes for TODO.md. ## Codex Plan (2025-09-19 - Restore `cargo test` Host Compilation) + - [x] Pinpoint the dependency pulling in `worker 0.0.24` and decide whether to remove or upgrade it so builds only use `worker 0.6.x`. - [x] Adjust the Cloudflare adapter to drop the outdated logger dependency (or replace it) while keeping logging behaviour sensible. - [x] Ensure workspace manifests stop requesting the older crate and update docs if they reference it. - [x] Re-run `cargo test` (or equivalent host checks) to confirm the build completes, then capture the outcome in TODO review notes. ## Codex Plan (2025-09-19 - Fastly Adapter Logger Module) + - [x] Add a dedicated `logger.rs` to the Fastly adapter mirroring the Cloudflare structure. - [x] Re-export the new logger helper from `lib.rs` and update call sites if needed. - [x] Ensure any docs or templates referencing Fastly logging stay accurate. - [x] Run `cargo test` to confirm the refactor behaves as before. ## 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] Prototype a coverage run on a representative crate (likely `edgezero-core`) to gauge feasibility and capture required tooling steps. - [x] Summarize recommended approach, prerequisites, and open questions in TODO review notes. ## 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. + +- [x] Expand unit tests for `edgezero_core::context::RequestContext` to cover extraction success/failure, JSON/form parsing, and path/query edge cases. +- [x] Add tests for `edgezero_core::error::EdgeError` constructors and conversion paths, ensuring status codes + messages are asserted. - [x] Exercise middleware chaining (`middleware.rs`) with mock handlers to cover both middleware execution and early returns. - [x] Write targeted tests for `Body` conversions (streaming JSON failure, `into_bytes` panic guard, etc.) and `Response` helper methods. - [x] Introduce extractor/responder tests to lift coverage in `extractor.rs` and `responder.rs`. -- [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. +- [x] Add compile-fail or snapshot tests for the `edgezero-macros::action` proc macro to cover unsupported inputs. +- [x] Run `cargo llvm-cov --package edgezero-core` (and any new test suites) to validate coverage improvements. ## 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. ## 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`. + +- Rebuilt `app-demo-core` against the redesigned `edgezero-core` by wiring routes through `RouterService::builder`, swapping controller extractors for `edgezero_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. + +- 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 `edgezero-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. +- No call-site changes were required—existing demos already target `edgezero_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). +- Verified `cargo-llvm-cov` is available via `asdf` and works against host crates: `cargo llvm-cov --package edgezero-core --lcov --output-path target/coverage/edgezero-core.lcov` produced an LCOV file and summary (~52% line coverage for `edgezero-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. + +- Added focused unit tests across `edgezero-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. +- `cargo test` passes, and `cargo llvm-cov --package edgezero-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. + +- Added workspace dependency bindings for `edgezero-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 `edgezero-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. ## Review (2025-09-19 07:35 UTC) -- Updated `anyedge_adapter_fastly::dispatch` to surface `fastly::Error` directly; demo entrypoints can now return `dispatch(&app, req)` without hand-rolling fallback responses. + +- Updated `edgezero_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. +- Script verifies `wasm32-wasip1` availability and builds both the Fastly adapter (`edgezero-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. +- Extended controller tests to cover streaming coercion and buffered rejection paths via the new API; `cargo test -p edgezero-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. - [x] Update the chosen doc section with the new prerequisites and cross-check formatting/links. ## Codex Plan (2025-09-20 - Fastly Wasm Test Investigation) -- [x] Reproduce the failing Fastly wasm tests via `cargo test --features fastly --target wasm32-wasip1` in `crates/anyedge-adapter-fastly`. + +- [x] Reproduce the failing Fastly wasm tests via `cargo test --features fastly --target wasm32-wasip1` in `crates/edgezero-adapter-fastly`. - [x] Inspect recent Fastly runtime changes to pinpoint incompatibilities (target env, required runner, feature flags). - [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. ## 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. - [x] Mirror the same decompression helper in the Cloudflare adapter so both adapters share behaviour. @@ -331,93 +381,110 @@ High-level backlog and decisions to drive the next milestones. - [x] Update docs (if needed) to reflect the new dependency or behaviour. ## 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] Introduce a compression helper module in `edgezero-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. - [x] Update Cloudflare adapter to use the same helper, removing duplicate code and imports. -- [x] Add unit tests in `anyedge-core` covering gzip/brotli decoding via the helper. +- [x] Add unit tests in `edgezero-core` covering gzip/brotli decoding via the helper. - [x] Re-run adapter/core tests to confirm everything compiles and passes. ## 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). ## 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] Bring `edgezero_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. ## 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. +- Host-side adapter tests pass (`cargo test -p edgezero-adapter-fastly`, `cargo test -p edgezero-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. + +- Added `compression.rs` to `edgezero-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`). +- Workspace dependencies updated (`async-stream` shared, `futures` promoted for core) and host tests pass (`cargo test -p edgezero-core`, `cargo test -p edgezero-adapter-fastly`, `cargo test -p edgezero-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. + +- Added `#![cfg_attr(target_arch = "wasm32", no_main)]` and imported `edgezero_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 `edgezero-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. + +- `edgezero_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. +- Updated CLI templates so newly scaffolded apps use `edgezero_adapter_fastly::dispatch` / `edgezero_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] Add focused tests in `crates/edgezero-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] Update `crates/edgezero-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. diff --git a/crates/anyedge-cli/README.md b/crates/anyedge-cli/README.md deleted file mode 100644 index a12fe81..0000000 --- a/crates/anyedge-cli/README.md +++ /dev/null @@ -1,40 +0,0 @@ -# anyedge-cli - -Command-line tooling for the AnyEdge framework. The CLI handles scaffolding, local development, and (soon) build/deploy flows across edge adapters. - -## Feature Flags & Optional Demo Dependency - -The crate exposes two cargo features: - -| Feature | Description | Enabled by default | -|----------------|----------------------------------------------------------|--------------------| -| `cli` | Builds the command-line interface (`anyedge` binary). | ✅ | -| `dev-example` | Pulls in `examples/app-demo/app-demo-core` so `anyedge dev` can boot the bundled demo app. Enable only when you want the sample router available. | ❌ | - -When you just need the CLI functionality (e.g. packaging for distribution), build without the demo feature: - -```bash -cargo build -p anyedge-cli --no-default-features --features cli -``` - -For contributors working on the demo, enable the extra feature: - -```bash -cargo run -p anyedge-cli --features "cli,dev-example" -- dev -``` - -## Commands - -_(summaries only; see `anyedge --help` for details)_ - -- `anyedge new ` – Scaffold a new AnyEdge project (templates still evolving). -- `anyedge dev` – Serve the current project locally (add `--features dev-example` to run the bundled demo). -- `anyedge build --adapter fastly` – Compile the Fastly crate to `wasm32-wasip1` and drop the artifact in `pkg/`. -- `anyedge deploy --adapter fastly` – Invoke the Fastly CLI (`fastly compute deploy`) from the detected Fastly crate. -- `anyedge serve --adapter fastly` – Run `fastly compute serve` in the Fastly crate directory for local testing (requires Fastly CLI). - -## Developing the CLI - -- Keep the demo dependency optional so downstream consumers aren’t forced to ship example code. -- Update both the CLI templates and `examples/app-demo` when changing scaffolded project structure. -- Run `cargo test -p anyedge-cli` and `cargo fmt` before opening a PR. diff --git a/crates/anyedge-cli/src/templates/core/src/lib.rs.hbs b/crates/anyedge-cli/src/templates/core/src/lib.rs.hbs deleted file mode 100644 index 501739c..0000000 --- a/crates/anyedge-cli/src/templates/core/src/lib.rs.hbs +++ /dev/null @@ -1,3 +0,0 @@ -mod handlers; - -anyedge_core::app!("../../anyedge.toml"); diff --git a/crates/anyedge-adapter-axum/Cargo.toml b/crates/edgezero-adapter-axum/Cargo.toml similarity index 81% rename from crates/anyedge-adapter-axum/Cargo.toml rename to crates/edgezero-adapter-axum/Cargo.toml index 08433c5..c7bb1b7 100644 --- a/crates/anyedge-adapter-axum/Cargo.toml +++ b/crates/edgezero-adapter-axum/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "anyedge-adapter-axum" +name = "edgezero-adapter-axum" edition = { workspace = true } version = { workspace = true } authors = { workspace = true } @@ -8,11 +8,11 @@ license = { workspace = true } [features] default = ["axum"] axum = ["dep:axum", "dep:tokio", "dep:tower", "dep:futures-util", "dep:reqwest"] -cli = ["dep:anyedge-adapter", "anyedge-adapter/cli", "dep:ctor", "dep:toml", "dep:walkdir"] +cli = ["dep:edgezero-adapter", "edgezero-adapter/cli", "dep:ctor", "dep:toml", "dep:walkdir"] [dependencies] -anyedge-adapter = { path = "../anyedge-adapter", optional = true, features = ["cli"] } -anyedge-core = { path = "../anyedge-core" } +edgezero-adapter = { path = "../edgezero-adapter", optional = true, features = ["cli"] } +edgezero-core = { path = "../edgezero-core" } anyhow = { workspace = true } async-trait = { workspace = true } axum = { workspace = true, optional = true } diff --git a/crates/anyedge-adapter-axum/src/cli.rs b/crates/edgezero-adapter-axum/src/cli.rs similarity index 92% rename from crates/anyedge-adapter-axum/src/cli.rs rename to crates/edgezero-adapter-axum/src/cli.rs index c8b54f4..ec79d45 100644 --- a/crates/anyedge-adapter-axum/src/cli.rs +++ b/crates/edgezero-adapter-axum/src/cli.rs @@ -2,15 +2,15 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use anyedge_adapter::cli_support::{ +use ctor::ctor; +use edgezero_adapter::cli_support::{ find_manifest_upwards, find_workspace_root, path_distance, read_package_name, }; -use anyedge_adapter::scaffold::{ +use edgezero_adapter::scaffold::{ register_adapter_blueprint, AdapterBlueprint, AdapterFileSpec, CommandTemplates, DependencySpec, LoggingDefaults, ManifestSpec, ReadmeInfo, TemplateRegistration, }; -use anyedge_adapter::{register_adapter, Adapter, AdapterAction}; -use ctor::ctor; +use edgezero_adapter::{register_adapter, Adapter, AdapterAction}; use toml::Value; use walkdir::WalkDir; @@ -46,16 +46,16 @@ static AXUM_FILE_SPECS: &[AdapterFileSpec] = &[ static AXUM_DEPENDENCIES: &[DependencySpec] = &[ DependencySpec { - key: "dep_anyedge_core_axum", - repo_crate: "crates/anyedge-core", - fallback: "anyedge-core = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-core\" }", + key: "dep_edgezero_core_axum", + repo_crate: "crates/edgezero-core", + fallback: "edgezero-core = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-core\" }", features: &[], }, DependencySpec { - key: "dep_anyedge_adapter_axum", - repo_crate: "crates/anyedge-adapter-axum", + key: "dep_edgezero_adapter_axum", + repo_crate: "crates/edgezero-adapter-axum", fallback: - "anyedge-adapter-axum = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-adapter-axum\", default-features = false }", + "edgezero-adapter-axum = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-adapter-axum\", default-features = false }", features: &["axum"], }, ]; @@ -64,8 +64,8 @@ static AXUM_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { id: "axum", display_name: "Axum", crate_suffix: "adapter-axum", - dependency_crate: "anyedge-adapter-axum", - dependency_repo_path: "crates/anyedge-adapter-axum", + dependency_crate: "edgezero-adapter-axum", + dependency_repo_path: "crates/edgezero-adapter-axum", template_registrations: AXUM_TEMPLATE_REGISTRATIONS, files: AXUM_FILE_SPECS, extra_dirs: &["src"], @@ -91,7 +91,7 @@ static AXUM_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { dev_heading: "{display} (local)", dev_steps: &["cd {crate_dir}", "cargo run"], }, - run_module: "anyedge_adapter_axum", + run_module: "edgezero_adapter_axum", }; struct AxumCliAdapter; @@ -152,7 +152,7 @@ fn locate_project() -> Result { fn run_cargo(project: &AxumProject, subcommand: &str, extra_args: &[String]) -> Result<(), String> { let display = project.crate_dir.display(); println!( - "[anyedge] Axum {subcommand} ({}) in {} (port: {})", + "[edgezero] Axum {subcommand} ({}) in {} (port: {})", project.crate_name, display, project.port ); let mut command = Command::new("cargo"); @@ -276,7 +276,7 @@ fn read_axum_project(manifest: &Path) -> Result { #[cfg(test)] mod tests { use super::*; - use anyedge_adapter::cli_support::find_manifest_upwards; + use edgezero_adapter::cli_support::find_manifest_upwards; use tempfile::tempdir; #[test] diff --git a/crates/anyedge-adapter-axum/src/context.rs b/crates/edgezero-adapter-axum/src/context.rs similarity index 92% rename from crates/anyedge-adapter-axum/src/context.rs rename to crates/edgezero-adapter-axum/src/context.rs index bca74ba..6fc8d9e 100644 --- a/crates/anyedge-adapter-axum/src/context.rs +++ b/crates/edgezero-adapter-axum/src/context.rs @@ -1,6 +1,6 @@ use std::net::SocketAddr; -use anyedge_core::http::Request; +use edgezero_core::http::Request; /// Axum-specific context data attached to each request. #[derive(Clone, Debug)] @@ -21,8 +21,8 @@ impl AxumRequestContext { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::request_builder; + use edgezero_core::body::Body; + use edgezero_core::http::request_builder; #[test] fn inserts_and_reads_context() { diff --git a/crates/anyedge-adapter-axum/src/dev_server.rs b/crates/edgezero-adapter-axum/src/dev_server.rs similarity index 89% rename from crates/anyedge-adapter-axum/src/dev_server.rs rename to crates/edgezero-adapter-axum/src/dev_server.rs index 4083866..ea73567 100644 --- a/crates/anyedge-adapter-axum/src/dev_server.rs +++ b/crates/edgezero-adapter-axum/src/dev_server.rs @@ -6,15 +6,15 @@ use tokio::runtime::Builder as RuntimeBuilder; use tokio::signal; use tower::{service_fn, Service}; -use anyedge_core::app::Hooks; -use anyedge_core::manifest::ManifestLoader; -use anyedge_core::router::RouterService; +use edgezero_core::app::Hooks; +use edgezero_core::manifest::ManifestLoader; +use edgezero_core::router::RouterService; use log::LevelFilter; use simple_logger::SimpleLogger; -use crate::service::AnyEdgeAxumService; +use crate::service::EdgeZeroAxumService; -/// Configuration used when running the dev server embedding AnyEdge into Axum. +/// Configuration used when running the dev server embedding EdgeZero into Axum. #[derive(Clone)] pub struct AxumDevServerConfig { pub addr: SocketAddr, @@ -30,7 +30,7 @@ impl Default for AxumDevServerConfig { } } -/// Blocking dev server runner used by the AnyEdge CLI. +/// Blocking dev server runner used by the EdgeZero CLI. pub struct AxumDevServer { router: RouterService, config: AxumDevServerConfig, @@ -70,7 +70,7 @@ impl AxumDevServer { let listener = tokio::net::TcpListener::from_std(listener) .context("failed to adopt std listener into tokio")?; - let service = AnyEdgeAxumService::new(router); + let service = EdgeZeroAxumService::new(router); let router = Router::new().fallback_service(service_fn(move |req| { let mut svc = service.clone(); async move { svc.call(req).await } diff --git a/crates/anyedge-adapter-axum/src/lib.rs b/crates/edgezero-adapter-axum/src/lib.rs similarity index 87% rename from crates/anyedge-adapter-axum/src/lib.rs rename to crates/edgezero-adapter-axum/src/lib.rs index 4ef0072..0be160d 100644 --- a/crates/anyedge-adapter-axum/src/lib.rs +++ b/crates/edgezero-adapter-axum/src/lib.rs @@ -1,4 +1,4 @@ -//! Axum adapter for AnyEdge routers and applications. +//! Axum adapter for EdgeZero routers and applications. #[cfg(feature = "axum")] mod context; @@ -27,4 +27,4 @@ pub use request::into_core_request; #[cfg(feature = "axum")] pub use response::into_axum_response; #[cfg(feature = "axum")] -pub use service::AnyEdgeAxumService; +pub use service::EdgeZeroAxumService; diff --git a/crates/anyedge-adapter-axum/src/proxy.rs b/crates/edgezero-adapter-axum/src/proxy.rs similarity index 93% rename from crates/anyedge-adapter-axum/src/proxy.rs rename to crates/edgezero-adapter-axum/src/proxy.rs index b0cd8f3..4b17e5f 100644 --- a/crates/anyedge-adapter-axum/src/proxy.rs +++ b/crates/edgezero-adapter-axum/src/proxy.rs @@ -1,10 +1,10 @@ use std::time::Duration; -use anyedge_core::body::Body; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{HeaderName, HeaderValue, Method, StatusCode}; -use anyedge_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use async_trait::async_trait; +use edgezero_core::body::Body; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{HeaderName, HeaderValue, Method, StatusCode}; +use edgezero_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use futures_util::StreamExt; use reqwest::{header, Client}; diff --git a/crates/anyedge-adapter-axum/src/request.rs b/crates/edgezero-adapter-axum/src/request.rs similarity index 95% rename from crates/anyedge-adapter-axum/src/request.rs rename to crates/edgezero-adapter-axum/src/request.rs index 563252a..b85ebaf 100644 --- a/crates/anyedge-adapter-axum/src/request.rs +++ b/crates/edgezero-adapter-axum/src/request.rs @@ -1,18 +1,18 @@ use std::net::SocketAddr; -use anyedge_core::body::Body; -use anyedge_core::http::Request as CoreRequest; -use anyedge_core::proxy::ProxyHandle; use axum::body::Body as AxumBody; use axum::extract::connect_info::ConnectInfo; use axum::http::Request; +use edgezero_core::body::Body; +use edgezero_core::http::Request as CoreRequest; +use edgezero_core::proxy::ProxyHandle; use http::header::CONTENT_TYPE; use http::HeaderValue; use crate::context::AxumRequestContext; use crate::proxy::AxumProxyClient; -/// Convert an Axum/Hyper request into an AnyEdge core request while preserving streaming bodies +/// Convert an Axum/Hyper request into an EdgeZero core request while preserving streaming bodies /// and exposing connection metadata through `AxumRequestContext`. pub async fn into_core_request(request: Request) -> Result { let (parts, body) = request.into_parts(); @@ -80,8 +80,8 @@ fn is_json_content_type(value: &HeaderValue) -> bool { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::Method; + use edgezero_core::body::Body; + use edgezero_core::http::Method; #[tokio::test] async fn converts_request_and_records_connect_info() { diff --git a/crates/anyedge-adapter-axum/src/response.rs b/crates/edgezero-adapter-axum/src/response.rs similarity index 90% rename from crates/anyedge-adapter-axum/src/response.rs rename to crates/edgezero-adapter-axum/src/response.rs index d6d7d11..46dc38f 100644 --- a/crates/anyedge-adapter-axum/src/response.rs +++ b/crates/edgezero-adapter-axum/src/response.rs @@ -4,14 +4,14 @@ use futures::executor::block_on; use futures_util::{pin_mut, StreamExt}; use tracing::error; -use anyedge_core::body::Body; -use anyedge_core::http::Response as CoreResponse; +use edgezero_core::body::Body; +use edgezero_core::http::Response as CoreResponse; -/// Convert an AnyEdge response into one consumable by Axum/Hyper. +/// Convert an EdgeZero response into one consumable by Axum/Hyper. /// /// Streaming responses are collected into an in-memory buffer. While this sacrifices /// incremental flushing, it keeps the adapter compatible with the non-`Send` streaming type used by -/// `anyedge_core::Body` and works well for local development. +/// `edgezero_core::Body` and works well for local development. pub fn into_axum_response(response: CoreResponse) -> Response { let (parts, body) = response.into_parts(); let body = match body { @@ -52,8 +52,8 @@ pub fn into_axum_response(response: CoreResponse) -> Response { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::{response_builder, StatusCode}; + use edgezero_core::body::Body; + use edgezero_core::http::{response_builder, StatusCode}; use futures::stream; #[test] diff --git a/crates/anyedge-adapter-axum/src/service.rs b/crates/edgezero-adapter-axum/src/service.rs similarity index 82% rename from crates/anyedge-adapter-axum/src/service.rs rename to crates/edgezero-adapter-axum/src/service.rs index 43cfa55..9c04bfe 100644 --- a/crates/anyedge-adapter-axum/src/service.rs +++ b/crates/edgezero-adapter-axum/src/service.rs @@ -10,24 +10,24 @@ use http::StatusCode; use tokio::{runtime::Handle, task}; use tower::Service; -use anyedge_core::router::RouterService; +use edgezero_core::router::RouterService; use crate::request::into_core_request; use crate::response::into_axum_response; -/// Tower service that adapts AnyEdge router requests to Axum/Hyper compatible responses. +/// Tower service that adapts EdgeZero router requests to Axum/Hyper compatible responses. #[derive(Clone)] -pub struct AnyEdgeAxumService { +pub struct EdgeZeroAxumService { router: RouterService, } -impl AnyEdgeAxumService { +impl EdgeZeroAxumService { pub fn new(router: RouterService) -> Self { Self { router } } } -impl Service> for AnyEdgeAxumService { +impl Service> for EdgeZeroAxumService { type Response = Response; type Error = Infallible; type Future = Pin> + Send>>; @@ -60,10 +60,10 @@ impl Service> for AnyEdgeAxumService { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::context::RequestContext; - use anyedge_core::error::EdgeError; - use anyedge_core::http::{response_builder, StatusCode}; + use edgezero_core::body::Body; + use edgezero_core::context::RequestContext; + use edgezero_core::error::EdgeError; + use edgezero_core::http::{response_builder, StatusCode}; use tower::ServiceExt; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -77,7 +77,7 @@ mod tests { Ok::<_, EdgeError>(response) }) .build(); - let mut service = AnyEdgeAxumService::new(router); + let mut service = EdgeZeroAxumService::new(router); let request = Request::builder().uri("/").body(AxumBody::empty()).unwrap(); let response = service.ready().await.unwrap().call(request).await.unwrap(); diff --git a/crates/anyedge-adapter-axum/src/templates/Cargo.toml.hbs b/crates/edgezero-adapter-axum/src/templates/Cargo.toml.hbs similarity index 85% rename from crates/anyedge-adapter-axum/src/templates/Cargo.toml.hbs rename to crates/edgezero-adapter-axum/src/templates/Cargo.toml.hbs index a0306ce..225ae5d 100644 --- a/crates/anyedge-adapter-axum/src/templates/Cargo.toml.hbs +++ b/crates/edgezero-adapter-axum/src/templates/Cargo.toml.hbs @@ -10,8 +10,8 @@ path = "src/main.rs" [dependencies] {{proj_core}} = { path = "../{{proj_core}}" } -{{{dep_anyedge_adapter_axum}}} -anyedge-core = { workspace = true } +{{{dep_edgezero_adapter_axum}}} +edgezero-core = { workspace = true } anyhow = { workspace = true } axum = { workspace = true } log = { workspace = true } diff --git a/crates/anyedge-adapter-axum/src/templates/axum.toml.hbs b/crates/edgezero-adapter-axum/src/templates/axum.toml.hbs similarity index 100% rename from crates/anyedge-adapter-axum/src/templates/axum.toml.hbs rename to crates/edgezero-adapter-axum/src/templates/axum.toml.hbs diff --git a/crates/anyedge-adapter-axum/src/templates/src/main.rs.hbs b/crates/edgezero-adapter-axum/src/templates/src/main.rs.hbs similarity index 55% rename from crates/anyedge-adapter-axum/src/templates/src/main.rs.hbs rename to crates/edgezero-adapter-axum/src/templates/src/main.rs.hbs index 87f8e51..5a4b532 100644 --- a/crates/anyedge-adapter-axum/src/templates/src/main.rs.hbs +++ b/crates/edgezero-adapter-axum/src/templates/src/main.rs.hbs @@ -1,7 +1,7 @@ use {{proj_core_mod}}::App; fn main() { - if let Err(err) = anyedge_adapter_axum::run_app::(include_str!("../../../anyedge.toml")) { + if let Err(err) = edgezero_adapter_axum::run_app::(include_str!("../../../edgezero.toml")) { eprintln!("axum adapter failed: {err}"); std::process::exit(1); } diff --git a/crates/anyedge-adapter-cloudflare/.cargo/config.toml b/crates/edgezero-adapter-cloudflare/.cargo/config.toml similarity index 100% rename from crates/anyedge-adapter-cloudflare/.cargo/config.toml rename to crates/edgezero-adapter-cloudflare/.cargo/config.toml diff --git a/crates/anyedge-adapter-cloudflare/.gitignore b/crates/edgezero-adapter-cloudflare/.gitignore similarity index 100% rename from crates/anyedge-adapter-cloudflare/.gitignore rename to crates/edgezero-adapter-cloudflare/.gitignore diff --git a/crates/anyedge-adapter-cloudflare/Cargo.toml b/crates/edgezero-adapter-cloudflare/Cargo.toml similarity index 75% rename from crates/anyedge-adapter-cloudflare/Cargo.toml rename to crates/edgezero-adapter-cloudflare/Cargo.toml index 65898ed..ed1306e 100644 --- a/crates/anyedge-adapter-cloudflare/Cargo.toml +++ b/crates/edgezero-adapter-cloudflare/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "anyedge-adapter-cloudflare" +name = "edgezero-adapter-cloudflare" edition = { workspace = true } version = { workspace = true } authors = { workspace = true } @@ -8,11 +8,11 @@ license = { workspace = true } [features] default = [] cloudflare = ["dep:worker"] -cli = ["dep:anyedge-adapter", "anyedge-adapter/cli", "dep:ctor", "dep:walkdir"] +cli = ["dep:edgezero-adapter", "edgezero-adapter/cli", "dep:ctor", "dep:walkdir"] [dependencies] -anyedge-core = { path = "../anyedge-core" } -anyedge-adapter = { path = "../anyedge-adapter", optional = true, features = ["cli"] } +edgezero-core = { path = "../edgezero-core" } +edgezero-adapter = { path = "../edgezero-adapter", optional = true, features = ["cli"] } async-trait = { workspace = true } brotli = { workspace = true } bytes = { workspace = true } diff --git a/crates/anyedge-adapter-cloudflare/package.json b/crates/edgezero-adapter-cloudflare/package.json similarity index 100% rename from crates/anyedge-adapter-cloudflare/package.json rename to crates/edgezero-adapter-cloudflare/package.json diff --git a/crates/anyedge-adapter-cloudflare/src/cli.rs b/crates/edgezero-adapter-cloudflare/src/cli.rs similarity index 88% rename from crates/anyedge-adapter-cloudflare/src/cli.rs rename to crates/edgezero-adapter-cloudflare/src/cli.rs index 50a2fa0..a78865f 100644 --- a/crates/anyedge-adapter-cloudflare/src/cli.rs +++ b/crates/edgezero-adapter-cloudflare/src/cli.rs @@ -2,15 +2,15 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use anyedge_adapter::cli_support::{ +use ctor::ctor; +use edgezero_adapter::cli_support::{ find_manifest_upwards, find_workspace_root, path_distance, read_package_name, }; -use anyedge_adapter::scaffold::{ +use edgezero_adapter::scaffold::{ register_adapter_blueprint, AdapterBlueprint, AdapterFileSpec, CommandTemplates, DependencySpec, LoggingDefaults, ManifestSpec, ReadmeInfo, TemplateRegistration, }; -use anyedge_adapter::{register_adapter, Adapter, AdapterAction}; -use ctor::ctor; +use edgezero_adapter::{register_adapter, Adapter, AdapterAction}; use walkdir::WalkDir; const TARGET_TRIPLE: &str = "wasm32-unknown-unknown"; @@ -150,23 +150,23 @@ static CLOUDFLARE_FILE_SPECS: &[AdapterFileSpec] = &[ static CLOUDFLARE_DEPENDENCIES: &[DependencySpec] = &[ DependencySpec { - key: "dep_anyedge_core_cloudflare", - repo_crate: "crates/anyedge-core", - fallback: "anyedge-core = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-core\", default-features = false }", + key: "dep_edgezero_core_cloudflare", + repo_crate: "crates/edgezero-core", + fallback: "edgezero-core = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-core\", default-features = false }", features: &[], }, DependencySpec { - key: "dep_anyedge_adapter_cloudflare", - repo_crate: "crates/anyedge-adapter-cloudflare", + key: "dep_edgezero_adapter_cloudflare", + repo_crate: "crates/edgezero-adapter-cloudflare", fallback: - "anyedge-adapter-cloudflare = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-adapter-cloudflare\", default-features = false }", + "edgezero-adapter-cloudflare = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-adapter-cloudflare\", default-features = false }", features: &[], }, DependencySpec { - key: "dep_anyedge_adapter_cloudflare_wasm", - repo_crate: "crates/anyedge-adapter-cloudflare", + key: "dep_edgezero_adapter_cloudflare_wasm", + repo_crate: "crates/edgezero-adapter-cloudflare", fallback: - "anyedge-adapter-cloudflare = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-adapter-cloudflare\", default-features = false, features = [\"cloudflare\"] }", + "edgezero-adapter-cloudflare = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-adapter-cloudflare\", default-features = false, features = [\"cloudflare\"] }", features: &["cloudflare"], }, ]; @@ -175,8 +175,8 @@ static CLOUDFLARE_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { id: "cloudflare", display_name: "Cloudflare Workers", crate_suffix: "adapter-cloudflare", - dependency_crate: "anyedge-adapter-cloudflare", - dependency_repo_path: "crates/anyedge-adapter-cloudflare", + dependency_crate: "edgezero-adapter-cloudflare", + dependency_repo_path: "crates/edgezero-adapter-cloudflare", template_registrations: CLOUDFLARE_TEMPLATE_REGISTRATIONS, files: CLOUDFLARE_FILE_SPECS, extra_dirs: &["src", ".cargo"], @@ -202,7 +202,7 @@ static CLOUDFLARE_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { dev_heading: "{display} (local)", dev_steps: &["cd {crate_dir}", "wrangler dev"], }, - run_module: "anyedge_adapter_cloudflare", + run_module: "edgezero_adapter_cloudflare", }; static CLOUDFLARE_ADAPTER: CloudflareCliAdapter = CloudflareCliAdapter; @@ -216,7 +216,7 @@ impl Adapter for CloudflareCliAdapter { match action { AdapterAction::Build => build().map(|artifact| { println!( - "[anyedge] Cloudflare build artifact -> {}", + "[edgezero] Cloudflare build artifact -> {}", artifact.display() ); }), diff --git a/crates/anyedge-adapter-cloudflare/src/context.rs b/crates/edgezero-adapter-cloudflare/src/context.rs similarity index 95% rename from crates/anyedge-adapter-cloudflare/src/context.rs rename to crates/edgezero-adapter-cloudflare/src/context.rs index 650cea1..d3bb888 100644 --- a/crates/anyedge-adapter-cloudflare/src/context.rs +++ b/crates/edgezero-adapter-cloudflare/src/context.rs @@ -1,6 +1,6 @@ use std::sync::Arc; -use anyedge_core::http::Request; +use edgezero_core::http::Request; use worker::{Context, Env}; /// Adapter-specific context stored alongside each request to expose Worker APIs. diff --git a/crates/anyedge-adapter-cloudflare/src/lib.rs b/crates/edgezero-adapter-cloudflare/src/lib.rs similarity index 95% rename from crates/anyedge-adapter-cloudflare/src/lib.rs rename to crates/edgezero-adapter-cloudflare/src/lib.rs index 4cf0513..0c4dcba 100644 --- a/crates/anyedge-adapter-cloudflare/src/lib.rs +++ b/crates/edgezero-adapter-cloudflare/src/lib.rs @@ -44,7 +44,7 @@ pub trait AppExt { } #[cfg(all(feature = "cloudflare", target_arch = "wasm32"))] -impl AppExt for anyedge_core::app::App { +impl AppExt for edgezero_core::app::App { fn dispatch<'a>( &'a self, req: worker::Request, @@ -58,7 +58,7 @@ impl AppExt for anyedge_core::app::App { } #[cfg(all(feature = "cloudflare", target_arch = "wasm32"))] -pub async fn run_app( +pub async fn run_app( req: worker::Request, env: worker::Env, ctx: worker::Context, diff --git a/crates/anyedge-adapter-cloudflare/src/proxy.rs b/crates/edgezero-adapter-cloudflare/src/proxy.rs similarity index 94% rename from crates/anyedge-adapter-cloudflare/src/proxy.rs rename to crates/edgezero-adapter-cloudflare/src/proxy.rs index 1522c88..f6e5e77 100644 --- a/crates/anyedge-adapter-cloudflare/src/proxy.rs +++ b/crates/edgezero-adapter-cloudflare/src/proxy.rs @@ -1,10 +1,10 @@ -use anyedge_core::body::Body; -use anyedge_core::compression::{decode_brotli_stream, decode_gzip_stream}; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{header, HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Uri}; -use anyedge_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use async_trait::async_trait; use bytes::Bytes; +use edgezero_core::body::Body; +use edgezero_core::compression::{decode_brotli_stream, decode_gzip_stream}; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{header, HeaderMap, HeaderName, HeaderValue, Method, StatusCode, Uri}; +use edgezero_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use futures_util::stream::{self, LocalBoxStream, StreamExt}; use futures_util::TryStreamExt; use std::io; @@ -28,7 +28,7 @@ impl ProxyClient for CloudflareProxyClient { let mut proxy_response = convert_response(&mut cf_response).await?; proxy_response .headers_mut() - .insert("x-anyedge-proxy", HeaderValue::from_static("cloudflare")); + .insert("x-edgezero-proxy", HeaderValue::from_static("cloudflare")); Ok(proxy_response) } } diff --git a/crates/anyedge-adapter-cloudflare/src/request.rs b/crates/edgezero-adapter-cloudflare/src/request.rs similarity index 92% rename from crates/anyedge-adapter-cloudflare/src/request.rs rename to crates/edgezero-adapter-cloudflare/src/request.rs index 05e445f..bd30427 100644 --- a/crates/anyedge-adapter-cloudflare/src/request.rs +++ b/crates/edgezero-adapter-cloudflare/src/request.rs @@ -1,11 +1,11 @@ use crate::proxy::CloudflareProxyClient; use crate::response::from_core_response; use crate::CloudflareRequestContext; -use anyedge_core::app::App; -use anyedge_core::body::Body; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{request_builder, Method as CoreMethod, Request, Uri}; -use anyedge_core::proxy::ProxyHandle; +use edgezero_core::app::App; +use edgezero_core::body::Body; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{request_builder, Method as CoreMethod, Request, Uri}; +use edgezero_core::proxy::ProxyHandle; use worker::{ Context, Env, Error as WorkerError, Method, Request as CfRequest, Response as CfResponse, }; diff --git a/crates/anyedge-adapter-cloudflare/src/response.rs b/crates/edgezero-adapter-cloudflare/src/response.rs similarity index 93% rename from crates/anyedge-adapter-cloudflare/src/response.rs rename to crates/edgezero-adapter-cloudflare/src/response.rs index d07130c..08e8a4f 100644 --- a/crates/anyedge-adapter-cloudflare/src/response.rs +++ b/crates/edgezero-adapter-cloudflare/src/response.rs @@ -1,6 +1,6 @@ -use anyedge_core::body::Body; -use anyedge_core::error::EdgeError; -use anyedge_core::http::Response; +use edgezero_core::body::Body; +use edgezero_core::error::EdgeError; +use edgezero_core::http::Response; use futures_util::StreamExt; use worker::{Error as WorkerError, Response as CfResponse}; @@ -35,9 +35,9 @@ pub fn from_core_response(response: Response) -> Result { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::response_builder; use bytes::Bytes; + use edgezero_core::body::Body; + use edgezero_core::http::response_builder; use futures_util::{stream, StreamExt}; #[test] diff --git a/crates/anyedge-adapter-cloudflare/src/templates/.cargo/config.toml.hbs b/crates/edgezero-adapter-cloudflare/src/templates/.cargo/config.toml.hbs similarity index 100% rename from crates/anyedge-adapter-cloudflare/src/templates/.cargo/config.toml.hbs rename to crates/edgezero-adapter-cloudflare/src/templates/.cargo/config.toml.hbs diff --git a/crates/anyedge-adapter-cloudflare/src/templates/Cargo.toml.hbs b/crates/edgezero-adapter-cloudflare/src/templates/Cargo.toml.hbs similarity index 61% rename from crates/anyedge-adapter-cloudflare/src/templates/Cargo.toml.hbs rename to crates/edgezero-adapter-cloudflare/src/templates/Cargo.toml.hbs index 86f31e3..e4be161 100644 --- a/crates/anyedge-adapter-cloudflare/src/templates/Cargo.toml.hbs +++ b/crates/edgezero-adapter-cloudflare/src/templates/Cargo.toml.hbs @@ -10,14 +10,14 @@ path = "src/main.rs" [features] default = ["cloudflare"] -cloudflare = ["anyedge-adapter-cloudflare/cloudflare"] +cloudflare = ["edgezero-adapter-cloudflare/cloudflare"] [dependencies] {{proj_core}} = { path = "../{{proj_core}}" } -{{{dep_anyedge_adapter_cloudflare}}} -anyedge-core = { workspace = true } +{{{dep_edgezero_adapter_cloudflare}}} +edgezero-core = { workspace = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -{{{dep_anyedge_core_cloudflare}}} -{{{dep_anyedge_adapter_cloudflare_wasm}}} +{{{dep_edgezero_core_cloudflare}}} +{{{dep_edgezero_adapter_cloudflare_wasm}}} worker = { workspace = true } diff --git a/crates/anyedge-adapter-cloudflare/src/templates/src/main.rs.hbs b/crates/edgezero-adapter-cloudflare/src/templates/src/main.rs.hbs similarity index 86% rename from crates/anyedge-adapter-cloudflare/src/templates/src/main.rs.hbs rename to crates/edgezero-adapter-cloudflare/src/templates/src/main.rs.hbs index 658b6e1..853598e 100644 --- a/crates/anyedge-adapter-cloudflare/src/templates/src/main.rs.hbs +++ b/crates/edgezero-adapter-cloudflare/src/templates/src/main.rs.hbs @@ -8,7 +8,7 @@ use {{proj_core_mod}}::App; #[cfg(target_arch = "wasm32")] #[event(fetch)] pub async fn main(req: Request, env: Env, ctx: Context) -> Result { - anyedge_adapter_cloudflare::run_app::(req, env, ctx).await + edgezero_adapter_cloudflare::run_app::(req, env, ctx).await } #[cfg(not(target_arch = "wasm32"))] diff --git a/crates/anyedge-adapter-cloudflare/src/templates/wrangler.toml.hbs b/crates/edgezero-adapter-cloudflare/src/templates/wrangler.toml.hbs similarity index 100% rename from crates/anyedge-adapter-cloudflare/src/templates/wrangler.toml.hbs rename to crates/edgezero-adapter-cloudflare/src/templates/wrangler.toml.hbs diff --git a/crates/anyedge-adapter-cloudflare/tests/contract.rs b/crates/edgezero-adapter-cloudflare/tests/contract.rs similarity index 90% rename from crates/anyedge-adapter-cloudflare/tests/contract.rs rename to crates/edgezero-adapter-cloudflare/tests/contract.rs index bfa00a2..192885d 100644 --- a/crates/anyedge-adapter-cloudflare/tests/contract.rs +++ b/crates/edgezero-adapter-cloudflare/tests/contract.rs @@ -1,12 +1,12 @@ #![cfg(all(feature = "cloudflare", target_arch = "wasm32"))] -use anyedge_adapter_cloudflare::{ +use bytes::Bytes; +use edgezero_adapter_cloudflare::{ dispatch, from_core_response, into_core_request, CloudflareRequestContext, }; -use anyedge_core::{ +use edgezero_core::{ response_builder, App, Body, EdgeError, Method, RequestContext, RouterService, StatusCode, }; -use bytes::Bytes; use futures::stream; use wasm_bindgen::JsValue; use wasm_bindgen_test::*; @@ -17,7 +17,7 @@ use worker::{ wasm_bindgen_test_configure!(run_in_browser); fn build_test_app() -> App { - async fn capture_uri(ctx: RequestContext) -> Result { + async fn capture_uri(ctx: RequestContext) -> Result { let body = Body::text(ctx.request().uri().to_string()); let response = response_builder() .status(StatusCode::OK) @@ -26,7 +26,7 @@ fn build_test_app() -> App { Ok(response) } - async fn mirror_body(ctx: RequestContext) -> Result { + async fn mirror_body(ctx: RequestContext) -> Result { let bytes = ctx.request().body().as_bytes().to_vec(); let response = response_builder() .status(StatusCode::OK) @@ -35,7 +35,7 @@ fn build_test_app() -> App { Ok(response) } - async fn stream_response(_ctx: RequestContext) -> Result { + async fn stream_response(_ctx: RequestContext) -> Result { let chunks = stream::iter(vec![ Bytes::from_static(b"chunk-1"), Bytes::from_static(b"chunk-2"), @@ -65,7 +65,7 @@ fn cf_request(method: CfMethod, path: &str, body: Option<&[u8]>) -> CfRequest { let headers = worker::Headers::new().expect("headers"); headers.set("host", "example.com").expect("host header"); - headers.set("x-anyedge-test", "1").expect("custom header"); + headers.set("x-edgezero-test", "1").expect("custom header"); init.with_headers(headers); if let Some(bytes) = body { @@ -96,7 +96,7 @@ async fn into_core_request_preserves_method_uri_headers_body_and_context() { let header = core_request .headers() - .get("x-anyedge-test") + .get("x-edgezero-test") .and_then(|value| value.to_str().ok()); assert_eq!(header, Some("1")); @@ -109,7 +109,7 @@ async fn into_core_request_preserves_method_uri_headers_body_and_context() { async fn from_core_response_translates_status_headers_and_streaming_body() { let response = response_builder() .status(StatusCode::CREATED) - .header("x-anyedge-res", "1") + .header("x-edgezero-res", "1") .body(Body::stream(stream::iter(vec![ Bytes::from_static(b"hello"), Bytes::from_static(b" "), @@ -120,7 +120,7 @@ async fn from_core_response_translates_status_headers_and_streaming_body() { let cf_response = from_core_response(response).expect("cf response"); assert_eq!(cf_response.status_code(), StatusCode::CREATED.as_u16()); - let header = cf_response.headers().get("x-anyedge-res").unwrap(); + let header = cf_response.headers().get("x-edgezero-res").unwrap(); assert_eq!(header.as_deref(), Some("1")); let bytes = cf_response.bytes().await.expect("bytes"); diff --git a/crates/anyedge-adapter-fastly/.cargo/config.toml b/crates/edgezero-adapter-fastly/.cargo/config.toml similarity index 100% rename from crates/anyedge-adapter-fastly/.cargo/config.toml rename to crates/edgezero-adapter-fastly/.cargo/config.toml diff --git a/crates/anyedge-adapter-fastly/.gitignore b/crates/edgezero-adapter-fastly/.gitignore similarity index 100% rename from crates/anyedge-adapter-fastly/.gitignore rename to crates/edgezero-adapter-fastly/.gitignore diff --git a/crates/anyedge-adapter-fastly/Cargo.toml b/crates/edgezero-adapter-fastly/Cargo.toml similarity index 75% rename from crates/anyedge-adapter-fastly/Cargo.toml rename to crates/edgezero-adapter-fastly/Cargo.toml index 920745f..5602404 100644 --- a/crates/anyedge-adapter-fastly/Cargo.toml +++ b/crates/edgezero-adapter-fastly/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "anyedge-adapter-fastly" +name = "edgezero-adapter-fastly" edition = { workspace = true } version = { workspace = true } authors = { workspace = true } @@ -7,12 +7,12 @@ license = { workspace = true } [features] default = [] -cli = ["dep:anyedge-adapter", "anyedge-adapter/cli", "dep:ctor", "dep:walkdir"] +cli = ["dep:edgezero-adapter", "edgezero-adapter/cli", "dep:ctor", "dep:walkdir"] fastly = ["dep:fastly", "dep:log-fastly"] [dependencies] -anyedge-core = { path = "../anyedge-core" } -anyedge-adapter = { path = "../anyedge-adapter", optional = true, features = ["cli"] } +edgezero-core = { path = "../edgezero-core" } +edgezero-adapter = { path = "../edgezero-adapter", optional = true, features = ["cli"] } async-stream = { workspace = true } async-trait = { workspace = true } brotli = { workspace = true } diff --git a/crates/anyedge-adapter-fastly/src/cli.rs b/crates/edgezero-adapter-fastly/src/cli.rs similarity index 89% rename from crates/anyedge-adapter-fastly/src/cli.rs rename to crates/edgezero-adapter-fastly/src/cli.rs index 5619396..1ee4d0b 100644 --- a/crates/anyedge-adapter-fastly/src/cli.rs +++ b/crates/edgezero-adapter-fastly/src/cli.rs @@ -2,15 +2,15 @@ use std::fs; use std::path::{Path, PathBuf}; use std::process::Command; -use anyedge_adapter::cli_support::{ +use ctor::ctor; +use edgezero_adapter::cli_support::{ find_manifest_upwards, find_workspace_root, path_distance, read_package_name, }; -use anyedge_adapter::scaffold::{ +use edgezero_adapter::scaffold::{ register_adapter_blueprint, AdapterBlueprint, AdapterFileSpec, CommandTemplates, DependencySpec, LoggingDefaults, ManifestSpec, ReadmeInfo, TemplateRegistration, }; -use anyedge_adapter::{register_adapter, Adapter, AdapterAction}; -use ctor::ctor; +use edgezero_adapter::{register_adapter, Adapter, AdapterAction}; use walkdir::WalkDir; pub fn build(extra_args: &[String]) -> Result { @@ -143,23 +143,23 @@ static FASTLY_FILE_SPECS: &[AdapterFileSpec] = &[ static FASTLY_DEPENDENCIES: &[DependencySpec] = &[ DependencySpec { - key: "dep_anyedge_core_fastly", - repo_crate: "crates/anyedge-core", - fallback: "anyedge-core = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-core\", default-features = false }", + key: "dep_edgezero_core_fastly", + repo_crate: "crates/edgezero-core", + fallback: "edgezero-core = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-core\", default-features = false }", features: &[], }, DependencySpec { - key: "dep_anyedge_adapter_fastly", - repo_crate: "crates/anyedge-adapter-fastly", + key: "dep_edgezero_adapter_fastly", + repo_crate: "crates/edgezero-adapter-fastly", fallback: - "anyedge-adapter-fastly = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-adapter-fastly\", default-features = false }", + "edgezero-adapter-fastly = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-adapter-fastly\", default-features = false }", features: &[], }, DependencySpec { - key: "dep_anyedge_adapter_fastly_wasm", - repo_crate: "crates/anyedge-adapter-fastly", + key: "dep_edgezero_adapter_fastly_wasm", + repo_crate: "crates/edgezero-adapter-fastly", fallback: - "anyedge-adapter-fastly = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-adapter-fastly\", default-features = false, features = [\"fastly\"] }", + "edgezero-adapter-fastly = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-adapter-fastly\", default-features = false, features = [\"fastly\"] }", features: &["fastly"], }, ]; @@ -168,8 +168,8 @@ static FASTLY_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { id: "fastly", display_name: "Fastly Compute@Edge", crate_suffix: "adapter-fastly", - dependency_crate: "anyedge-adapter-fastly", - dependency_repo_path: "crates/anyedge-adapter-fastly", + dependency_crate: "edgezero-adapter-fastly", + dependency_repo_path: "crates/edgezero-adapter-fastly", template_registrations: FASTLY_TEMPLATE_REGISTRATIONS, files: FASTLY_FILE_SPECS, extra_dirs: &["src", ".cargo"], @@ -195,7 +195,7 @@ static FASTLY_BLUEPRINT: AdapterBlueprint = AdapterBlueprint { dev_heading: "{display} (local)", dev_steps: &["cd {crate_dir}", "fastly compute serve"], }, - run_module: "anyedge_adapter_fastly", + run_module: "edgezero_adapter_fastly", }; static FASTLY_ADAPTER: FastlyCliAdapter = FastlyCliAdapter; @@ -209,7 +209,7 @@ impl Adapter for FastlyCliAdapter { match action { AdapterAction::Build => { let artifact = build(args)?; - println!("[anyedge] Fastly build complete -> {}", artifact.display()); + println!("[edgezero] Fastly build complete -> {}", artifact.display()); Ok(()) } AdapterAction::Deploy => deploy(args), @@ -308,7 +308,7 @@ fn locate_artifact( #[cfg(test)] mod tests { use super::*; - use anyedge_adapter::cli_support::read_package_name; + use edgezero_adapter::cli_support::read_package_name; use tempfile::tempdir; #[test] diff --git a/crates/anyedge-adapter-fastly/src/context.rs b/crates/edgezero-adapter-fastly/src/context.rs similarity index 92% rename from crates/anyedge-adapter-fastly/src/context.rs rename to crates/edgezero-adapter-fastly/src/context.rs index 50a8206..54f0708 100644 --- a/crates/anyedge-adapter-fastly/src/context.rs +++ b/crates/edgezero-adapter-fastly/src/context.rs @@ -1,6 +1,6 @@ use std::net::IpAddr; -use anyedge_core::http::Request; +use edgezero_core::http::Request; /// Fastly-specific context data stored on each request. #[derive(Clone, Debug)] @@ -21,8 +21,8 @@ impl FastlyRequestContext { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::request_builder; + use edgezero_core::body::Body; + use edgezero_core::http::request_builder; use std::net::IpAddr; use std::str::FromStr; diff --git a/crates/anyedge-adapter-fastly/src/lib.rs b/crates/edgezero-adapter-fastly/src/lib.rs similarity index 83% rename from crates/anyedge-adapter-fastly/src/lib.rs rename to crates/edgezero-adapter-fastly/src/lib.rs index 8dd7b11..5603831 100644 --- a/crates/anyedge-adapter-fastly/src/lib.rs +++ b/crates/edgezero-adapter-fastly/src/lib.rs @@ -1,5 +1,5 @@ //! Utilities for bridging Fastly Compute@Edge requests into the -//! `anyedge-core` service abstractions. +//! `edgezero-core` service abstractions. #[cfg(feature = "cli")] pub mod cli; @@ -31,8 +31,8 @@ pub struct FastlyLogging { } #[cfg(feature = "fastly")] -impl From for FastlyLogging { - fn from(config: anyedge_core::manifest::ResolvedLoggingConfig) -> Self { +impl From for FastlyLogging { + fn from(config: edgezero_core::manifest::ResolvedLoggingConfig) -> Self { Self { endpoint: config.endpoint, level: config.level.into(), @@ -66,24 +66,24 @@ pub trait AppExt { } #[cfg(feature = "fastly")] -impl AppExt for anyedge_core::app::App { +impl AppExt for edgezero_core::app::App { fn dispatch(&self, req: fastly::Request) -> Result { dispatch(self, req) } } #[cfg(feature = "fastly")] -pub fn run_app( +pub fn run_app( manifest_src: &str, req: fastly::Request, ) -> Result { - let manifest_loader = anyedge_core::manifest::ManifestLoader::load_from_str(manifest_src); + let manifest_loader = edgezero_core::manifest::ManifestLoader::load_from_str(manifest_src); let logging = manifest_loader.manifest().logging_or_default("fastly"); run_app_with_logging::(logging.into(), req) } #[cfg(feature = "fastly")] -pub fn run_app_with_logging( +pub fn run_app_with_logging( logging: FastlyLogging, req: fastly::Request, ) -> Result { @@ -102,10 +102,10 @@ mod tests { #[test] fn fastly_logging_from_manifest_converts_defaults() { - let config = anyedge_core::manifest::ResolvedLoggingConfig { + let config = edgezero_core::manifest::ResolvedLoggingConfig { endpoint: Some("endpoint".to_string()), echo_stdout: Some(false), - level: anyedge_core::manifest::LogLevel::Debug, + level: edgezero_core::manifest::LogLevel::Debug, }; let logging: FastlyLogging = config.into(); diff --git a/crates/anyedge-adapter-fastly/src/logger.rs b/crates/edgezero-adapter-fastly/src/logger.rs similarity index 100% rename from crates/anyedge-adapter-fastly/src/logger.rs rename to crates/edgezero-adapter-fastly/src/logger.rs diff --git a/crates/anyedge-adapter-fastly/src/proxy.rs b/crates/edgezero-adapter-fastly/src/proxy.rs similarity index 94% rename from crates/anyedge-adapter-fastly/src/proxy.rs rename to crates/edgezero-adapter-fastly/src/proxy.rs index 862fd36..170b5b0 100644 --- a/crates/anyedge-adapter-fastly/src/proxy.rs +++ b/crates/edgezero-adapter-fastly/src/proxy.rs @@ -1,11 +1,11 @@ -use anyedge_core::body::Body; -use anyedge_core::compression::{decode_brotli_stream, decode_gzip_stream}; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{header, HeaderMap, HeaderValue, Method, Uri}; -use anyedge_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use async_stream::try_stream; use async_trait::async_trait; use bytes::Bytes; +use edgezero_core::body::Body; +use edgezero_core::compression::{decode_brotli_stream, decode_gzip_stream}; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{header, HeaderMap, HeaderValue, Method, Uri}; +use edgezero_core::proxy::{ProxyClient, ProxyRequest, ProxyResponse}; use fastly::{ http::body::StreamingBody, Backend, Request as FastlyRequest, Response as FastlyResponse, }; @@ -14,7 +14,7 @@ use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; use std::io::{self, Write}; -const BACKEND_PREFIX: &str = "anyedge-dynamic-"; +const BACKEND_PREFIX: &str = "edgezero-dynamic-"; pub struct FastlyProxyClient; @@ -34,7 +34,7 @@ impl ProxyClient for FastlyProxyClient { let mut proxy_response = convert_response(&mut fastly_response)?; proxy_response .headers_mut() - .insert("x-anyedge-proxy", HeaderValue::from_static("fastly")); + .insert("x-edgezero-proxy", HeaderValue::from_static("fastly")); Ok(proxy_response) } } diff --git a/crates/anyedge-adapter-fastly/src/request.rs b/crates/edgezero-adapter-fastly/src/request.rs similarity index 88% rename from crates/anyedge-adapter-fastly/src/request.rs rename to crates/edgezero-adapter-fastly/src/request.rs index 715d9a3..8a2cdb5 100644 --- a/crates/anyedge-adapter-fastly/src/request.rs +++ b/crates/edgezero-adapter-fastly/src/request.rs @@ -1,10 +1,10 @@ use std::io::Read; -use anyedge_core::app::App; -use anyedge_core::body::Body; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{request_builder, Request}; -use anyedge_core::proxy::ProxyHandle; +use edgezero_core::app::App; +use edgezero_core::body::Body; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{request_builder, Request}; +use edgezero_core::proxy::ProxyHandle; use fastly::{Error as FastlyError, Request as FastlyRequest, Response as FastlyResponse}; use futures::executor; diff --git a/crates/anyedge-adapter-fastly/src/response.rs b/crates/edgezero-adapter-fastly/src/response.rs similarity index 91% rename from crates/anyedge-adapter-fastly/src/response.rs rename to crates/edgezero-adapter-fastly/src/response.rs index a94c42f..617c501 100644 --- a/crates/anyedge-adapter-fastly/src/response.rs +++ b/crates/edgezero-adapter-fastly/src/response.rs @@ -1,6 +1,6 @@ -use anyedge_core::body::Body; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{Response, Uri}; +use edgezero_core::body::Body; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{Response, Uri}; use fastly::Response as FastlyResponse; use futures_util::StreamExt; use std::io::Write; @@ -36,9 +36,9 @@ pub fn parse_uri(uri: &str) -> Result { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::http::response_builder; use bytes::Bytes; + use edgezero_core::body::Body; + use edgezero_core::http::response_builder; use futures_util::stream; #[test] diff --git a/crates/anyedge-adapter-fastly/src/templates/.cargo/config.toml.hbs b/crates/edgezero-adapter-fastly/src/templates/.cargo/config.toml.hbs similarity index 100% rename from crates/anyedge-adapter-fastly/src/templates/.cargo/config.toml.hbs rename to crates/edgezero-adapter-fastly/src/templates/.cargo/config.toml.hbs diff --git a/crates/anyedge-adapter-fastly/src/templates/Cargo.toml.hbs b/crates/edgezero-adapter-fastly/src/templates/Cargo.toml.hbs similarity index 71% rename from crates/anyedge-adapter-fastly/src/templates/Cargo.toml.hbs rename to crates/edgezero-adapter-fastly/src/templates/Cargo.toml.hbs index 052a2bb..3fbc31f 100644 --- a/crates/anyedge-adapter-fastly/src/templates/Cargo.toml.hbs +++ b/crates/edgezero-adapter-fastly/src/templates/Cargo.toml.hbs @@ -10,15 +10,15 @@ path = "src/main.rs" [features] default = [] -fastly = ["anyedge-adapter-fastly/fastly"] +fastly = ["edgezero-adapter-fastly/fastly"] [dependencies] {{proj_core}} = { path = "../{{proj_core}}" } log = { workspace = true } -{{{dep_anyedge_adapter_fastly}}} +{{{dep_edgezero_adapter_fastly}}} [target.'cfg(target_arch = "wasm32")'.dependencies] -{{{dep_anyedge_core_fastly}}} -{{{dep_anyedge_adapter_fastly_wasm}}} +{{{dep_edgezero_core_fastly}}} +{{{dep_edgezero_adapter_fastly_wasm}}} fastly = { workspace = true } once_cell = { workspace = true } diff --git a/crates/anyedge-adapter-fastly/src/templates/fastly.toml.hbs b/crates/edgezero-adapter-fastly/src/templates/fastly.toml.hbs similarity index 100% rename from crates/anyedge-adapter-fastly/src/templates/fastly.toml.hbs rename to crates/edgezero-adapter-fastly/src/templates/fastly.toml.hbs diff --git a/crates/anyedge-adapter-fastly/src/templates/src/main.rs.hbs b/crates/edgezero-adapter-fastly/src/templates/src/main.rs.hbs similarity index 82% rename from crates/anyedge-adapter-fastly/src/templates/src/main.rs.hbs rename to crates/edgezero-adapter-fastly/src/templates/src/main.rs.hbs index 52dd9dc..0972d31 100644 --- a/crates/anyedge-adapter-fastly/src/templates/src/main.rs.hbs +++ b/crates/edgezero-adapter-fastly/src/templates/src/main.rs.hbs @@ -7,7 +7,7 @@ use {{proj_core_mod}}::App; #[cfg(target_arch = "wasm32")] #[fastly::main] pub fn main(req: Request) -> Result { - anyedge_adapter_fastly::run_app::(include_str!("../../../anyedge.toml"), req) + edgezero_adapter_fastly::run_app::(include_str!("../../../edgezero.toml"), req) } #[cfg(not(target_arch = "wasm32"))] diff --git a/crates/anyedge-adapter-fastly/tests/contract.rs b/crates/edgezero-adapter-fastly/tests/contract.rs similarity index 89% rename from crates/anyedge-adapter-fastly/tests/contract.rs rename to crates/edgezero-adapter-fastly/tests/contract.rs index 9ac23e3..f3c25b3 100644 --- a/crates/anyedge-adapter-fastly/tests/contract.rs +++ b/crates/edgezero-adapter-fastly/tests/contract.rs @@ -1,15 +1,15 @@ #![cfg(all(feature = "fastly", target_arch = "wasm32"))] -use anyedge_adapter_fastly::{ +use bytes::Bytes; +use edgezero_adapter_fastly::{ dispatch, from_core_response, into_core_request, FastlyRequestContext, }; -use anyedge_core::app::App; -use anyedge_core::body::Body; -use anyedge_core::context::RequestContext; -use anyedge_core::error::EdgeError; -use anyedge_core::http::{response_builder, Method, Response, StatusCode}; -use anyedge_core::router::RouterService; -use bytes::Bytes; +use edgezero_core::app::App; +use edgezero_core::body::Body; +use edgezero_core::context::RequestContext; +use edgezero_core::error::EdgeError; +use edgezero_core::http::{response_builder, Method, Response, StatusCode}; +use edgezero_core::router::RouterService; use fastly::http::{Method as FastlyMethod, StatusCode as FastlyStatus}; use fastly::Request as FastlyRequest; use futures::stream; @@ -58,7 +58,7 @@ fn build_test_app() -> App { fn fastly_request(method: FastlyMethod, path: &str, body: Option<&[u8]>) -> FastlyRequest { let mut req = FastlyRequest::new(method, path); req.set_header("host", "example.com"); - req.set_header("x-anyedge-test", "1"); + req.set_header("x-edgezero-test", "1"); if let Some(bytes) = body { req.set_body(bytes.to_vec()); } @@ -79,7 +79,7 @@ fn into_core_request_preserves_method_uri_headers_body_and_context() { let headers = core_request.headers(); assert_eq!( headers - .get("x-anyedge-test") + .get("x-edgezero-test") .and_then(|value| value.to_str().ok()), Some("1") ); @@ -94,7 +94,7 @@ fn into_core_request_preserves_method_uri_headers_body_and_context() { fn from_core_response_translates_status_headers_and_streaming_body() { let response = response_builder() .status(StatusCode::CREATED) - .header("x-anyedge-res", "1") + .header("x-edgezero-res", "1") .body(Body::stream(stream::iter(vec![ Bytes::from_static(b"hello"), Bytes::from_static(b" "), @@ -105,7 +105,7 @@ fn from_core_response_translates_status_headers_and_streaming_body() { let mut fastly_response = from_core_response(response).expect("fastly response"); assert_eq!(fastly_response.get_status(), FastlyStatus::CREATED); - assert!(fastly_response.get_header("x-anyedge-res").is_some()); + assert!(fastly_response.get_header("x-edgezero-res").is_some()); assert_eq!(fastly_response.take_body_bytes(), b"hello world"); } diff --git a/crates/anyedge-adapter/Cargo.toml b/crates/edgezero-adapter/Cargo.toml similarity index 71% rename from crates/anyedge-adapter/Cargo.toml rename to crates/edgezero-adapter/Cargo.toml index 3adb6e6..39130ee 100644 --- a/crates/anyedge-adapter/Cargo.toml +++ b/crates/edgezero-adapter/Cargo.toml @@ -1,8 +1,8 @@ [package] -name = "anyedge-adapter" +name = "edgezero-adapter" version = "0.1.0" edition = "2021" -description = "Adapter registry and traits for AnyEdge adapters" +description = "Adapter registry and traits for EdgeZero adapters" [features] default = [] diff --git a/crates/anyedge-adapter/src/cli_support.rs b/crates/edgezero-adapter/src/cli_support.rs similarity index 100% rename from crates/anyedge-adapter/src/cli_support.rs rename to crates/edgezero-adapter/src/cli_support.rs diff --git a/crates/anyedge-adapter/src/lib.rs b/crates/edgezero-adapter/src/lib.rs similarity index 100% rename from crates/anyedge-adapter/src/lib.rs rename to crates/edgezero-adapter/src/lib.rs diff --git a/crates/anyedge-adapter/src/registry.rs b/crates/edgezero-adapter/src/registry.rs similarity index 93% rename from crates/anyedge-adapter/src/registry.rs rename to crates/edgezero-adapter/src/registry.rs index acd114f..2f9616c 100644 --- a/crates/anyedge-adapter/src/registry.rs +++ b/crates/edgezero-adapter/src/registry.rs @@ -2,7 +2,7 @@ use once_cell::sync::Lazy; use std::collections::HashMap; use std::sync::RwLock; -/// Actions the AnyEdge CLI can request from an adapter implementation. +/// Actions the EdgeZero CLI can request from an adapter implementation. #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum AdapterAction { Build, @@ -10,7 +10,7 @@ pub enum AdapterAction { Serve, } -/// Interface implemented by adapter crates to integrate with the AnyEdge CLI. +/// Interface implemented by adapter crates to integrate with the EdgeZero CLI. pub trait Adapter: Sync + Send { /// Name used to reference the adapter (case-insensitive). fn name(&self) -> &'static str; @@ -26,7 +26,7 @@ static REGISTRY: Lazy>> = pub fn register_adapter(adapter: &'static dyn Adapter) { let mut registry = REGISTRY .write() - .expect("anyedge adapter registry lock poisoned"); + .expect("edgezero adapter registry lock poisoned"); registry.insert(adapter.name().to_ascii_lowercase(), adapter); } @@ -34,7 +34,7 @@ pub fn register_adapter(adapter: &'static dyn Adapter) { pub fn get_adapter(name: &str) -> Option<&'static dyn Adapter> { let registry = REGISTRY .read() - .expect("anyedge adapter registry lock poisoned"); + .expect("edgezero adapter registry lock poisoned"); registry.get(&name.to_ascii_lowercase()).copied() } @@ -42,7 +42,7 @@ pub fn get_adapter(name: &str) -> Option<&'static dyn Adapter> { pub fn registered_adapters() -> Vec { let registry = REGISTRY .read() - .expect("anyedge adapter registry lock poisoned"); + .expect("edgezero adapter registry lock poisoned"); let mut names: Vec = registry.keys().cloned().collect(); names.sort(); names diff --git a/crates/anyedge-adapter/src/scaffold.rs b/crates/edgezero-adapter/src/scaffold.rs similarity index 94% rename from crates/anyedge-adapter/src/scaffold.rs rename to crates/edgezero-adapter/src/scaffold.rs index 8055cc8..3cfbae5 100644 --- a/crates/anyedge-adapter/src/scaffold.rs +++ b/crates/edgezero-adapter/src/scaffold.rs @@ -83,7 +83,7 @@ static BLUEPRINT_REGISTRY: Lazy Vec<&'static AdapterBlueprint> { let registry = BLUEPRINT_REGISTRY .read() - .expect("anyedge blueprint registry lock poisoned"); + .expect("edgezero blueprint registry lock poisoned"); let mut values: Vec<&'static AdapterBlueprint> = registry.values().copied().collect(); values.sort_by(|a, b| a.id.cmp(b.id)); values @@ -117,8 +117,8 @@ mod tests { id: "alpha", display_name: "Alpha", crate_suffix: "adapter-alpha", - dependency_crate: "anyedge-adapter-alpha", - dependency_repo_path: "crates/anyedge-adapter-alpha", + dependency_crate: "edgezero-adapter-alpha", + dependency_repo_path: "crates/edgezero-adapter-alpha", template_registrations: &[FIRST_TEMPLATE], files: &[AdapterFileSpec { template: "first", @@ -159,8 +159,8 @@ mod tests { id: "beta", display_name: "Beta", crate_suffix: "adapter-beta", - dependency_crate: "anyedge-adapter-beta", - dependency_repo_path: "crates/anyedge-adapter-beta", + dependency_crate: "edgezero-adapter-beta", + dependency_repo_path: "crates/edgezero-adapter-beta", template_registrations: &[SECOND_TEMPLATE], files: &[AdapterFileSpec { template: "second", diff --git a/crates/anyedge-cli/Cargo.toml b/crates/edgezero-cli/Cargo.toml similarity index 53% rename from crates/anyedge-cli/Cargo.toml rename to crates/edgezero-cli/Cargo.toml index 88ccd09..900d0c3 100644 --- a/crates/anyedge-cli/Cargo.toml +++ b/crates/edgezero-cli/Cargo.toml @@ -1,15 +1,15 @@ [package] -name = "anyedge-cli" +name = "edgezero-cli" version = "0.1.0" edition = "2021" -description = "AnyEdge CLI: build and deploy to multiple edge adapters" +description = "EdgeZero CLI: build and deploy to multiple edge adapters" [dependencies] -anyedge-core = { workspace = true } -anyedge-adapter = { path = "../anyedge-adapter" } -anyedge-adapter-axum = { workspace = true, features = ["cli", "axum"], optional = true } -anyedge-adapter-cloudflare = { workspace = true, features = ["cli"], optional = true } -anyedge-adapter-fastly = { workspace = true, features = ["cli"], optional = true } +edgezero-core = { workspace = true } +edgezero-adapter = { path = "../edgezero-adapter" } +edgezero-adapter-axum = { workspace = true, features = ["cli", "axum"], optional = true } +edgezero-adapter-cloudflare = { workspace = true, features = ["cli"], optional = true } +edgezero-adapter-fastly = { workspace = true, features = ["cli"], optional = true } app-demo-core = { path = "../../examples/app-demo/crates/app-demo-core", package = "app-demo-core", optional = true } clap = { version = "4", features = ["derive"], optional = true } futures = { workspace = true } @@ -28,9 +28,9 @@ tempfile = { workspace = true } [features] default = [ "cli", - "anyedge-adapter-axum", - "anyedge-adapter-fastly", - "anyedge-adapter-cloudflare", + "edgezero-adapter-axum", + "edgezero-adapter-fastly", + "edgezero-adapter-cloudflare", ] cli = ["dep:clap"] dev-example = ["dep:app-demo-core"] diff --git a/crates/edgezero-cli/README.md b/crates/edgezero-cli/README.md new file mode 100644 index 0000000..0ea16fb --- /dev/null +++ b/crates/edgezero-cli/README.md @@ -0,0 +1,40 @@ +# edgezero-cli + +Command-line tooling for the EdgeZero framework. The CLI handles scaffolding, local development, and (soon) build/deploy flows across edge adapters. + +## Feature Flags & Optional Demo Dependency + +The crate exposes two cargo features: + +| Feature | Description | Enabled by default | +|----------------|----------------------------------------------------------|--------------------| +| `cli` | Builds the command-line interface (`edgezero` binary). | ✅ | +| `dev-example` | Pulls in `examples/app-demo/app-demo-core` so `edgezero dev` can boot the bundled demo app. Enable only when you want the sample router available. | ❌ | + +When you just need the CLI functionality (e.g. packaging for distribution), build without the demo feature: + +```bash +cargo build -p edgezero-cli --no-default-features --features cli +``` + +For contributors working on the demo, enable the extra feature: + +```bash +cargo run -p edgezero-cli --features "cli,dev-example" -- dev +``` + +## Commands + +_(summaries only; see `edgezero --help` for details)_ + +- `edgezero new ` – Scaffold a new EdgeZero project (templates still evolving). +- `edgezero dev` – Serve the current project locally (add `--features dev-example` to run the bundled demo). +- `edgezero build --adapter fastly` – Compile the Fastly crate to `wasm32-wasip1` and drop the artifact in `pkg/`. +- `edgezero deploy --adapter fastly` – Invoke the Fastly CLI (`fastly compute deploy`) from the detected Fastly crate. +- `edgezero serve --adapter fastly` – Run `fastly compute serve` in the Fastly crate directory for local testing (requires Fastly CLI). + +## Developing the CLI + +- Keep the demo dependency optional so downstream consumers aren't forced to ship example code. +- Update both the CLI templates and `examples/app-demo` when changing scaffolded project structure. +- Run `cargo test -p edgezero-cli` and `cargo fmt` before opening a PR. diff --git a/crates/anyedge-cli/build.rs b/crates/edgezero-cli/build.rs similarity index 97% rename from crates/anyedge-cli/build.rs rename to crates/edgezero-cli/build.rs index dcfc4d5..170a942 100644 --- a/crates/anyedge-cli/build.rs +++ b/crates/edgezero-cli/build.rs @@ -20,7 +20,7 @@ fn main() { let mut adapters: Vec = dependencies .into_iter() .filter_map(|(name, spec)| { - if !name.starts_with("anyedge-adapter-") { + if !name.starts_with("edgezero-adapter-") { return None; } let optional = match spec { diff --git a/crates/anyedge-cli/src/adapter.rs b/crates/edgezero-cli/src/adapter.rs similarity index 89% rename from crates/anyedge-cli/src/adapter.rs rename to crates/edgezero-cli/src/adapter.rs index 4d2a877..31d38e9 100644 --- a/crates/anyedge-cli/src/adapter.rs +++ b/crates/edgezero-cli/src/adapter.rs @@ -1,5 +1,5 @@ -use anyedge_adapter::{self as adapter_registry, AdapterAction}; -use anyedge_core::manifest::{Manifest, ManifestLoader, ResolvedEnvironment}; +use edgezero_adapter::{self as adapter_registry, AdapterAction}; +use edgezero_core::manifest::{Manifest, ManifestLoader, ResolvedEnvironment}; use std::path::Path; use std::process::Command; @@ -42,7 +42,7 @@ pub fn execute( if available.is_empty() { if manifest.is_none() { format!( - "adapter `{}` is not registered in this build. Provide an `anyedge.toml` (or set `ANYEDGE_MANIFEST`) so the CLI can load adapters, or rebuild `anyedge-cli` with the `{adapter_name}` adapter feature enabled.", + "adapter `{}` is not registered in this build. Provide an `edgezero.toml` (or set `EDGEZERO_MANIFEST`) so the CLI can load adapters, or rebuild `edgezero-cli` with the `{adapter_name}` adapter feature enabled.", adapter_name ) } else { @@ -77,7 +77,7 @@ fn run_shell( format!("{} {}", command, shell_join(adapter_args)) }; println!( - "[anyedge] executing `{}` for adapter `{}` in {}", + "[edgezero] executing `{}` for adapter `{}` in {}", full_command, adapter_name, cwd.display() @@ -185,24 +185,24 @@ fn manifest_command<'a>( #[cfg(test)] mod tests { use super::{apply_environment, ResolvedEnvironment}; - use anyedge_core::manifest::ResolvedEnvironmentBinding; + use edgezero_core::manifest::ResolvedEnvironmentBinding; use std::process::Command; #[test] fn apply_environment_sets_defaults_and_checks_secrets() { - std::env::remove_var("ANYEDGE_TEST_SECRET"); + std::env::remove_var("EDGEZERO_TEST_SECRET"); let env = ResolvedEnvironment { variables: vec![ResolvedEnvironmentBinding { name: "Base".into(), description: None, - env: "ANYEDGE_TEST_BASE".into(), + env: "EDGEZERO_TEST_BASE".into(), value: Some("https://demo".into()), }], secrets: vec![ResolvedEnvironmentBinding { name: "Secret".into(), description: None, - env: "ANYEDGE_TEST_SECRET".into(), + env: "EDGEZERO_TEST_SECRET".into(), value: None, }], }; @@ -212,16 +212,16 @@ mod tests { let result = apply_environment(adapter_name, &env, &mut Command::new("echo")); assert!(result.is_err()); - std::env::set_var("ANYEDGE_TEST_SECRET", "set"); + std::env::set_var("EDGEZERO_TEST_SECRET", "set"); let mut cmd = Command::new("echo"); apply_environment(adapter_name, &env, &mut cmd).expect("environment applied"); let has_var = cmd.get_envs().any(|(key, value)| { - key.to_str() == Some("ANYEDGE_TEST_BASE") + key.to_str() == Some("EDGEZERO_TEST_BASE") && value.and_then(|v| v.to_str()) == Some("https://demo") }); assert!(has_var); - std::env::remove_var("ANYEDGE_TEST_SECRET"); + std::env::remove_var("EDGEZERO_TEST_SECRET"); } #[test] diff --git a/crates/anyedge-cli/src/args.rs b/crates/edgezero-cli/src/args.rs similarity index 85% rename from crates/anyedge-cli/src/args.rs rename to crates/edgezero-cli/src/args.rs index 43f83a2..f9a5589 100644 --- a/crates/anyedge-cli/src/args.rs +++ b/crates/edgezero-cli/src/args.rs @@ -1,7 +1,7 @@ use clap::{Parser, Subcommand}; #[derive(Parser, Debug)] -#[command(name = "anyedge", about = "AnyEdge CLI")] +#[command(name = "edgezero", about = "EdgeZero CLI")] pub struct Args { #[command(subcommand)] pub cmd: Command, @@ -9,7 +9,7 @@ pub struct Args { #[derive(Subcommand, Debug)] pub enum Command { - /// Create a new AnyEdge app skeleton (multi-crate workspace) + /// Create a new EdgeZero app skeleton (multi-crate workspace) New(NewArgs), /// Build the project for a target edge Build { @@ -41,7 +41,7 @@ pub struct NewArgs { /// Directory to create the app in (default: current dir) #[arg(long)] pub dir: Option, - /// Force using a local path dependency to anyedge-core (if available) + /// Force using a local path dependency to edgezero-core (if available) #[arg(long)] pub local_core: bool, } @@ -53,7 +53,7 @@ mod tests { #[test] fn parses_new_command_with_defaults() { - let args = Args::try_parse_from(["anyedge", "new", "demo-app"]).expect("parse new"); + let args = Args::try_parse_from(["edgezero", "new", "demo-app"]).expect("parse new"); match args.cmd { Command::New(new_args) => { assert_eq!(new_args.name, "demo-app"); @@ -67,7 +67,7 @@ mod tests { #[test] fn parses_build_command_with_passthrough_args() { let args = Args::try_parse_from([ - "anyedge", + "edgezero", "build", "--adapter", "fastly", @@ -90,6 +90,6 @@ mod tests { #[test] fn missing_required_adapter_returns_error() { - assert!(Args::try_parse_from(["anyedge", "build"]).is_err()); + assert!(Args::try_parse_from(["edgezero", "build"]).is_err()); } } diff --git a/crates/anyedge-cli/src/dev_server.rs b/crates/edgezero-cli/src/dev_server.rs similarity index 78% rename from crates/anyedge-cli/src/dev_server.rs rename to crates/edgezero-cli/src/dev_server.rs index 8f881ae..7cb6e05 100644 --- a/crates/anyedge-cli/src/dev_server.rs +++ b/crates/edgezero-cli/src/dev_server.rs @@ -1,33 +1,33 @@ -#![cfg(feature = "anyedge-adapter-axum")] +#![cfg(feature = "edgezero-adapter-axum")] use std::net::SocketAddr; use std::path::PathBuf; -use anyedge_adapter_axum::{AxumDevServer, AxumDevServerConfig}; -use anyedge_core::manifest::ManifestLoader; -use anyedge_core::router::RouterService; +use edgezero_adapter_axum::{AxumDevServer, AxumDevServerConfig}; +use edgezero_core::manifest::ManifestLoader; +use edgezero_core::router::RouterService; use crate::adapter; use crate::adapter::Action; #[cfg(not(feature = "dev-example"))] -use anyedge_core::{action, extractor::Path, response::Text}; +use edgezero_core::{action, extractor::Path, response::Text}; -#[cfg(feature = "dev-example")] -use anyedge_core::app::Hooks; #[cfg(feature = "dev-example")] use app_demo_core::App; +#[cfg(feature = "dev-example")] +use edgezero_core::app::Hooks; pub fn run_dev() { match try_run_manifest_axum() { Ok(true) => return, Ok(false) => {} - Err(err) => eprintln!("[anyedge] dev manifest error: {err}"), + Err(err) => eprintln!("[edgezero] dev manifest error: {err}"), } let addr = SocketAddr::from(([127, 0, 0, 1], 8787)); println!( - "[anyedge] dev: starting local server on http://{}:{}", + "[edgezero] dev: starting local server on http://{}:{}", addr.ip(), addr.port() ); @@ -40,7 +40,7 @@ pub fn run_dev() { let server = AxumDevServer::with_config(router, config); if let Err(err) = server.run() { - eprintln!("[anyedge] dev server error: {err}"); + eprintln!("[edgezero] dev server error: {err}"); } } @@ -74,7 +74,7 @@ struct EchoParams { #[cfg(not(feature = "dev-example"))] #[action] async fn dev_root() -> Text<&'static str> { - Text::new("AnyEdge dev server") + Text::new("EdgeZero dev server") } #[cfg(not(feature = "dev-example"))] @@ -99,9 +99,9 @@ fn try_run_manifest_axum() -> Result { } fn load_manifest_optional() -> Result, String> { - let path = std::env::var("ANYEDGE_MANIFEST") + let path = std::env::var("EDGEZERO_MANIFEST") .map(PathBuf::from) - .unwrap_or_else(|_| PathBuf::from("anyedge.toml")); + .unwrap_or_else(|_| PathBuf::from("edgezero.toml")); match ManifestLoader::from_path(&path) { Ok(manifest) => Ok(Some(manifest)), diff --git a/crates/anyedge-cli/src/generator.rs b/crates/edgezero-cli/src/generator.rs similarity index 93% rename from crates/anyedge-cli/src/generator.rs rename to crates/edgezero-cli/src/generator.rs index 17d4176..d5ce207 100644 --- a/crates/anyedge-cli/src/generator.rs +++ b/crates/edgezero-cli/src/generator.rs @@ -2,8 +2,8 @@ use crate::args::NewArgs; use crate::scaffold::{ register_templates, resolve_dep_line, sanitize_crate_name, write_tmpl, ResolvedDependency, }; -use anyedge_adapter::scaffold; -use anyedge_adapter::scaffold::AdapterBlueprint; +use edgezero_adapter::scaffold; +use edgezero_adapter::scaffold::AdapterBlueprint; use handlebars::Handlebars; use serde_json::{Map, Value}; use std::collections::BTreeMap; @@ -43,7 +43,7 @@ impl ProjectLayout { )); } - println!("[anyedge] creating project at {}", out_dir.display()); + println!("[edgezero] creating project at {}", out_dir.display()); let crates_dir = out_dir.join("crates"); let core_name = format!("{}-core", name); @@ -99,7 +99,7 @@ pub fn generate_new(args: NewArgs) -> std::io::Result<()> { initialize_git_repo(&layout.out_dir); println!( - "[anyedge] created new multi-crate app at {}", + "[edgezero] created new multi-crate app at {}", layout.out_dir.display() ); @@ -152,8 +152,8 @@ fn resolve_core_dependency( } = resolve_dep_line( &layout.out_dir, cwd, - "crates/anyedge-core", - "anyedge-core = { git = \"ssh://git@github.com/stackpop/anyedge.git\", package = \"anyedge-core\", default-features = false }", + "crates/edgezero-core", + "edgezero-core = { git = \"ssh://git@github.com/stackpop/edgezero.git\", package = \"edgezero-core\", default-features = false }", &[], ); @@ -329,7 +329,7 @@ fn build_base_data( ); data.insert("proj_mod".into(), Value::String(layout.project_mod.clone())); data.insert( - "dep_anyedge_core".into(), + "dep_edgezero_core".into(), Value::String(core_crate_line.to_string()), ); @@ -378,7 +378,7 @@ fn render_templates( let mut hbs = Handlebars::new(); register_templates(&mut hbs); - println!("[anyedge] writing workspace files"); + println!("[edgezero] writing workspace files"); write_tmpl( &hbs, "root_Cargo_toml", @@ -387,9 +387,9 @@ fn render_templates( )?; write_tmpl( &hbs, - "root_anyedge_toml", + "root_edgezero_toml", data_value, - &layout.out_dir.join("anyedge.toml"), + &layout.out_dir.join("edgezero.toml"), )?; write_tmpl( &hbs, @@ -404,7 +404,7 @@ fn render_templates( &layout.out_dir.join(".gitignore"), )?; - println!("[anyedge] writing core crate {}", layout.core_name); + println!("[edgezero] writing core crate {}", layout.core_name); write_tmpl( &hbs, "core_Cargo_toml", @@ -426,7 +426,7 @@ fn render_templates( for context in adapter_contexts { println!( - "[anyedge] writing adapter crate {}", + "[edgezero] writing adapter crate {}", context.dir.file_name().unwrap().to_string_lossy() ); for file in context.blueprint.files { @@ -443,7 +443,7 @@ fn render_templates( } fn initialize_git_repo(out_dir: &Path) { - println!("[anyedge] initializing git repository"); + println!("[edgezero] initializing git repository"); match Command::new("git") .arg("init") .arg("--quiet") @@ -452,16 +452,16 @@ fn initialize_git_repo(out_dir: &Path) { { Ok(status) if status.success() => { println!( - "[anyedge] initialized empty Git repository in {}/.git/", + "[edgezero] initialized empty Git repository in {}/.git/", out_dir.display() ); } Ok(status) => { - eprintln!("[anyedge] warning: git init exited with status {status}"); + eprintln!("[edgezero] warning: git init exited with status {status}"); } Err(err) => { eprintln!( - "[anyedge] warning: failed to initialize git repository: {}", + "[edgezero] warning: failed to initialize git repository: {}", err ); } @@ -542,7 +542,7 @@ mod tests { let project_dir = temp.path().join("demo-app"); assert!(project_dir.is_dir(), "project directory created"); assert!(project_dir.join("Cargo.toml").exists()); - assert!(project_dir.join("anyedge.toml").exists()); + assert!(project_dir.join("edgezero.toml").exists()); assert!(project_dir.join(".gitignore").exists()); assert!(project_dir.join("README.md").exists()); assert!(project_dir.join("crates/demo-app-core/src/lib.rs").exists()); @@ -554,7 +554,7 @@ mod tests { assert!(cargo_toml.contains("crates/demo-app-adapter-fastly")); let manifest = - std::fs::read_to_string(project_dir.join("anyedge.toml")).expect("read anyedge.toml"); + std::fs::read_to_string(project_dir.join("edgezero.toml")).expect("read edgezero.toml"); assert!(manifest.contains("[adapters.cloudflare.adapter]")); assert!(manifest.contains("[adapters.fastly.adapter]")); diff --git a/crates/anyedge-cli/src/main.rs b/crates/edgezero-cli/src/main.rs similarity index 82% rename from crates/anyedge-cli/src/main.rs rename to crates/edgezero-cli/src/main.rs index 19b6624..d562934 100644 --- a/crates/anyedge-cli/src/main.rs +++ b/crates/edgezero-cli/src/main.rs @@ -1,10 +1,10 @@ -//! AnyEdge CLI. +//! EdgeZero CLI. #[cfg(feature = "cli")] mod adapter; #[cfg(feature = "cli")] mod args; -#[cfg(all(feature = "cli", feature = "anyedge-adapter-axum"))] +#[cfg(all(feature = "cli", feature = "edgezero-adapter-axum"))] mod dev_server; #[cfg(feature = "cli")] mod generator; @@ -12,7 +12,7 @@ mod generator; mod scaffold; #[cfg(feature = "cli")] -use anyedge_core::manifest::ManifestLoader; +use edgezero_core::manifest::ManifestLoader; #[cfg(feature = "cli")] use std::io::ErrorKind; #[cfg(feature = "cli")] @@ -27,7 +27,7 @@ fn main() { match args.cmd { Command::New(new_args) => { if let Err(e) = generator::generate_new(new_args) { - eprintln!("[anyedge] new error: {e}"); + eprintln!("[edgezero] new error: {e}"); std::process::exit(1); } } @@ -36,7 +36,7 @@ fn main() { adapter_args, } => { if let Err(err) = handle_build(&adapter, &adapter_args) { - eprintln!("[anyedge] build error: {err}"); + eprintln!("[edgezero] build error: {err}"); std::process::exit(1); } } @@ -45,26 +45,26 @@ fn main() { adapter_args, } => { if let Err(err) = handle_deploy(&adapter, &adapter_args) { - eprintln!("[anyedge] deploy error: {err}"); + eprintln!("[edgezero] deploy error: {err}"); std::process::exit(1); } } Command::Serve { adapter } => { if let Err(err) = handle_serve(&adapter) { - eprintln!("[anyedge] serve error: {err}"); + eprintln!("[edgezero] serve error: {err}"); std::process::exit(1); } } Command::Dev => { - #[cfg(feature = "anyedge-adapter-axum")] + #[cfg(feature = "edgezero-adapter-axum")] { dev_server::run_dev(); } - #[cfg(not(feature = "anyedge-adapter-axum"))] + #[cfg(not(feature = "edgezero-adapter-axum"))] { eprintln!( - "anyedge-cli built without `anyedge-adapter-axum`; rebuild with that feature to use `anyedge dev`." + "edgezero-cli built without `edgezero-adapter-axum`; rebuild with that feature to use `edgezero dev`." ); std::process::exit(1); } @@ -74,7 +74,7 @@ fn main() { #[cfg(not(feature = "cli"))] fn main() { - eprintln!("anyedge-cli built without `cli` feature. Rebuild with `--features cli`."); + eprintln!("edgezero-cli built without `cli` feature. Rebuild with `--features cli`."); } #[cfg(feature = "cli")] @@ -125,12 +125,12 @@ fn ensure_adapter_defined( let available: Vec = manifest.manifest().adapters.keys().cloned().collect(); if available.is_empty() { Err(format!( - "adapter `{}` is not configured in anyedge.toml (no adapters defined)", + "adapter `{}` is not configured in edgezero.toml (no adapters defined)", adapter_name )) } else { Err(format!( - "adapter `{}` is not configured in anyedge.toml (available: {})", + "adapter `{}` is not configured in edgezero.toml (available: {})", adapter_name, available.join(", ") )) @@ -142,9 +142,9 @@ fn ensure_adapter_defined( #[cfg(feature = "cli")] fn load_manifest_optional() -> Result, String> { - let path = std::env::var("ANYEDGE_MANIFEST") + let path = std::env::var("EDGEZERO_MANIFEST") .map(PathBuf::from) - .unwrap_or_else(|_| PathBuf::from("anyedge.toml")); + .unwrap_or_else(|_| PathBuf::from("edgezero.toml")); match ManifestLoader::from_path(&path) { Ok(loader) => Ok(Some(loader)), @@ -156,7 +156,7 @@ fn load_manifest_optional() -> Result, String> { #[cfg(all(test, feature = "cli"))] mod tests { use super::*; - use anyedge_core::manifest::ManifestLoader; + use edgezero_core::manifest::ManifestLoader; use std::fs; use std::sync::{Mutex, OnceLock}; use tempfile::TempDir; @@ -214,7 +214,7 @@ serve = "echo serve" let temp = TempDir::new().expect("temp dir"); let manifest_path = temp.path().join("missing.toml"); let manifest_str = manifest_path.to_string_lossy().into_owned(); - let _env = EnvOverride::set("ANYEDGE_MANIFEST", &manifest_str); + let _env = EnvOverride::set("EDGEZERO_MANIFEST", &manifest_str); let result = load_manifest_optional().expect("load result"); assert!(result.is_none()); } @@ -223,10 +223,10 @@ serve = "echo serve" fn load_manifest_optional_reads_manifest() { let _lock = manifest_guard().lock().expect("manifest guard"); let temp = TempDir::new().expect("temp dir"); - let manifest_path = temp.path().join("anyedge.toml"); + let manifest_path = temp.path().join("edgezero.toml"); fs::write(&manifest_path, BASIC_MANIFEST).expect("write manifest"); let manifest_str = manifest_path.to_string_lossy().into_owned(); - let _env = EnvOverride::set("ANYEDGE_MANIFEST", &manifest_str); + let _env = EnvOverride::set("EDGEZERO_MANIFEST", &manifest_str); let manifest = load_manifest_optional() .expect("load result") .expect("manifest present"); @@ -257,10 +257,10 @@ serve = "echo serve" fn handle_build_executes_manifest_command() { let _lock = manifest_guard().lock().expect("manifest guard"); let temp = TempDir::new().expect("temp dir"); - let manifest_path = temp.path().join("anyedge.toml"); + let manifest_path = temp.path().join("edgezero.toml"); fs::write(&manifest_path, BASIC_MANIFEST).expect("write manifest"); let manifest_str = manifest_path.to_string_lossy().into_owned(); - let _env = EnvOverride::set("ANYEDGE_MANIFEST", &manifest_str); + let _env = EnvOverride::set("EDGEZERO_MANIFEST", &manifest_str); let args: Vec = Vec::new(); handle_build("fastly", &args).expect("build command runs"); } @@ -270,10 +270,10 @@ serve = "echo serve" fn handle_deploy_executes_manifest_command() { let _lock = manifest_guard().lock().expect("manifest guard"); let temp = TempDir::new().expect("temp dir"); - let manifest_path = temp.path().join("anyedge.toml"); + let manifest_path = temp.path().join("edgezero.toml"); fs::write(&manifest_path, BASIC_MANIFEST).expect("write manifest"); let manifest_str = manifest_path.to_string_lossy().into_owned(); - let _env = EnvOverride::set("ANYEDGE_MANIFEST", &manifest_str); + let _env = EnvOverride::set("EDGEZERO_MANIFEST", &manifest_str); let args: Vec = Vec::new(); handle_deploy("fastly", &args).expect("deploy command runs"); } @@ -283,10 +283,10 @@ serve = "echo serve" fn handle_serve_executes_manifest_command() { let _lock = manifest_guard().lock().expect("manifest guard"); let temp = TempDir::new().expect("temp dir"); - let manifest_path = temp.path().join("anyedge.toml"); + let manifest_path = temp.path().join("edgezero.toml"); fs::write(&manifest_path, BASIC_MANIFEST).expect("write manifest"); let manifest_str = manifest_path.to_string_lossy().into_owned(); - let _env = EnvOverride::set("ANYEDGE_MANIFEST", &manifest_str); + let _env = EnvOverride::set("EDGEZERO_MANIFEST", &manifest_str); handle_serve("fastly").expect("serve command runs"); } } diff --git a/crates/anyedge-cli/src/scaffold.rs b/crates/edgezero-cli/src/scaffold.rs similarity index 96% rename from crates/anyedge-cli/src/scaffold.rs rename to crates/edgezero-cli/src/scaffold.rs index 34ddca7..24cf2ef 100644 --- a/crates/anyedge-cli/src/scaffold.rs +++ b/crates/edgezero-cli/src/scaffold.rs @@ -1,4 +1,4 @@ -use anyedge_adapter::scaffold; +use edgezero_adapter::scaffold; use handlebars::Handlebars; pub fn register_templates(hbs: &mut Handlebars) { @@ -9,8 +9,8 @@ pub fn register_templates(hbs: &mut Handlebars) { ) .unwrap(); hbs.register_template_string( - "root_anyedge_toml", - include_str!("templates/root/anyedge.toml.hbs"), + "root_edgezero_toml", + include_str!("templates/root/edgezero.toml.hbs"), ) .unwrap(); hbs.register_template_string( @@ -77,7 +77,7 @@ pub fn sanitize_crate_name(input: &str) -> String { } } if out.is_empty() { - "anyedge-app".to_string() + "edgezero-app".to_string() } else { out } @@ -169,7 +169,7 @@ mod tests { for name in [ "root_Cargo_toml", - "root_anyedge_toml", + "root_edgezero_toml", "root_README_md", "root_gitignore", "core_Cargo_toml", diff --git a/crates/anyedge-cli/src/templates/core/Cargo.toml.hbs b/crates/edgezero-cli/src/templates/core/Cargo.toml.hbs similarity index 91% rename from crates/anyedge-cli/src/templates/core/Cargo.toml.hbs rename to crates/edgezero-cli/src/templates/core/Cargo.toml.hbs index 617c1c2..6771574 100644 --- a/crates/anyedge-cli/src/templates/core/Cargo.toml.hbs +++ b/crates/edgezero-cli/src/templates/core/Cargo.toml.hbs @@ -5,7 +5,7 @@ edition = "2021" publish = false [dependencies] -{{{dep_anyedge_core}}} +{{{dep_edgezero_core}}} bytes = { workspace = true } futures = { workspace = true } serde = { workspace = true } diff --git a/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs b/crates/edgezero-cli/src/templates/core/src/handlers.rs.hbs similarity index 92% rename from crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs rename to crates/edgezero-cli/src/templates/core/src/handlers.rs.hbs index 2f266c8..1641a1f 100644 --- a/crates/anyedge-cli/src/templates/core/src/handlers.rs.hbs +++ b/crates/edgezero-cli/src/templates/core/src/handlers.rs.hbs @@ -1,11 +1,11 @@ -use anyedge_core::action; -use anyedge_core::body::Body; -use anyedge_core::context::RequestContext; -use anyedge_core::error::EdgeError; -use anyedge_core::extractor::{Headers, Json, Path}; -use anyedge_core::http::{self, Response, StatusCode, Uri}; -use anyedge_core::proxy::ProxyRequest; -use anyedge_core::response::Text; +use edgezero_core::action; +use edgezero_core::body::Body; +use edgezero_core::context::RequestContext; +use edgezero_core::error::EdgeError; +use edgezero_core::extractor::{Headers, Json, Path}; +use edgezero_core::http::{self, Response, StatusCode, Uri}; +use edgezero_core::proxy::ProxyRequest; +use edgezero_core::response::Text; use bytes::Bytes; use futures::{stream, StreamExt}; @@ -115,13 +115,13 @@ fn proxy_not_available_response() -> Result { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::context::RequestContext; - use anyedge_core::http::header::{HeaderName, HeaderValue}; - use anyedge_core::http::{request_builder, Method, StatusCode, Uri}; - use anyedge_core::params::PathParams; - use anyedge_core::proxy::{ProxyClient, ProxyHandle, ProxyResponse}; - use anyedge_core::response::IntoResponse; + use edgezero_core::body::Body; + use edgezero_core::context::RequestContext; + use edgezero_core::http::header::{HeaderName, HeaderValue}; + use edgezero_core::http::{request_builder, Method, StatusCode, Uri}; + use edgezero_core::params::PathParams; + use edgezero_core::proxy::{ProxyClient, ProxyHandle, ProxyResponse}; + use edgezero_core::response::IntoResponse; use async_trait::async_trait; use futures::{executor::block_on, StreamExt}; use std::collections::HashMap; diff --git a/crates/edgezero-cli/src/templates/core/src/lib.rs.hbs b/crates/edgezero-cli/src/templates/core/src/lib.rs.hbs new file mode 100644 index 0000000..d8939a1 --- /dev/null +++ b/crates/edgezero-cli/src/templates/core/src/lib.rs.hbs @@ -0,0 +1,3 @@ +mod handlers; + +edgezero_core::app!("../../edgezero.toml"); diff --git a/crates/anyedge-cli/src/templates/root/Cargo.toml.hbs b/crates/edgezero-cli/src/templates/root/Cargo.toml.hbs similarity index 100% rename from crates/anyedge-cli/src/templates/root/Cargo.toml.hbs rename to crates/edgezero-cli/src/templates/root/Cargo.toml.hbs diff --git a/crates/anyedge-cli/src/templates/root/README.md.hbs b/crates/edgezero-cli/src/templates/root/README.md.hbs similarity index 66% rename from crates/anyedge-cli/src/templates/root/README.md.hbs rename to crates/edgezero-cli/src/templates/root/README.md.hbs index 6a84955..376fc87 100644 --- a/crates/anyedge-cli/src/templates/root/README.md.hbs +++ b/crates/edgezero-cli/src/templates/root/README.md.hbs @@ -1,8 +1,8 @@ # {{name}} -This workspace demonstrates a multi-target AnyEdge app. +This workspace demonstrates a multi-target EdgeZero app. -- `crates/{{proj_core}}`: reusable application logic built with `anyedge-core`. +- `crates/{{proj_core}}`: reusable application logic built with `edgezero-core`. {{{readme_adapter_crates}}} ## Routes @@ -20,4 +20,4 @@ This workspace demonstrates a multi-target AnyEdge app. ## Configuration -Environment variables are declared in `anyedge.toml`. Set `API_BASE_URL` to the upstream origin you want `/proxy/...` to target and provide adapter-specific secrets (for example `API_TOKEN`) when deploying. +Environment variables are declared in `edgezero.toml`. Set `API_BASE_URL` to the upstream origin you want `/proxy/...` to target and provide adapter-specific secrets (for example `API_TOKEN`) when deploying. diff --git a/crates/anyedge-cli/src/templates/root/anyedge.toml.hbs b/crates/edgezero-cli/src/templates/root/edgezero.toml.hbs similarity index 90% rename from crates/anyedge-cli/src/templates/root/anyedge.toml.hbs rename to crates/edgezero-cli/src/templates/root/edgezero.toml.hbs index 8d547b9..dda437f 100644 --- a/crates/anyedge-cli/src/templates/root/anyedge.toml.hbs +++ b/crates/edgezero-cli/src/templates/root/edgezero.toml.hbs @@ -1,8 +1,8 @@ -# This manifest describes the shared AnyEdge application and its adapter-specific configurations. +# This manifest describes the shared EdgeZero application and its adapter-specific configurations. [app] name = "{{name}}" -middleware = ["anyedge_core::middleware::RequestLogger"] +middleware = ["edgezero_core::middleware::RequestLogger"] version = "0.1.0" kind = "http" entry = "crates/{{proj_core}}" diff --git a/crates/anyedge-cli/src/templates/root/gitignore.hbs b/crates/edgezero-cli/src/templates/root/gitignore.hbs similarity index 100% rename from crates/anyedge-cli/src/templates/root/gitignore.hbs rename to crates/edgezero-cli/src/templates/root/gitignore.hbs diff --git a/crates/anyedge-core/.gitignore b/crates/edgezero-core/.gitignore similarity index 100% rename from crates/anyedge-core/.gitignore rename to crates/edgezero-core/.gitignore diff --git a/crates/anyedge-core/Cargo.toml b/crates/edgezero-core/Cargo.toml similarity index 92% rename from crates/anyedge-core/Cargo.toml rename to crates/edgezero-core/Cargo.toml index 8808649..11838f7 100644 --- a/crates/anyedge-core/Cargo.toml +++ b/crates/edgezero-core/Cargo.toml @@ -1,12 +1,12 @@ [package] -name = "anyedge-core" +name = "edgezero-core" edition = { workspace = true } version = { workspace = true } authors = { workspace = true } license = { workspace = true } [dependencies] -anyedge-macros = { path = "../anyedge-macros" } +edgezero-macros = { path = "../edgezero-macros" } anyhow = { workspace = true } async-compression = { workspace = true } async-stream = { workspace = true } diff --git a/crates/anyedge-core/src/app.rs b/crates/edgezero-core/src/app.rs similarity index 96% rename from crates/anyedge-core/src/app.rs rename to crates/edgezero-core/src/app.rs index 2de2fe0..a09ec0f 100644 --- a/crates/anyedge-core/src/app.rs +++ b/crates/edgezero-core/src/app.rs @@ -1,6 +1,6 @@ use crate::router::RouterService; -const DEFAULT_APP_NAME: &str = "AnyEdge App"; +const DEFAULT_APP_NAME: &str = "EdgeZero App"; /// Lightweight container around a `RouterService` that can be extended via hook implementations. pub struct App { @@ -63,7 +63,7 @@ pub trait Hooks { /// Build the router service for the application. fn routes() -> RouterService; - /// Display name for the application. Defaults to `"AnyEdge App"`. + /// Display name for the application. Defaults to `"EdgeZero App"`. fn name() -> &'static str { App::default_name() } diff --git a/crates/anyedge-core/src/body.rs b/crates/edgezero-core/src/body.rs similarity index 100% rename from crates/anyedge-core/src/body.rs rename to crates/edgezero-core/src/body.rs diff --git a/crates/anyedge-core/src/compression.rs b/crates/edgezero-core/src/compression.rs similarity index 100% rename from crates/anyedge-core/src/compression.rs rename to crates/edgezero-core/src/compression.rs diff --git a/crates/anyedge-core/src/context.rs b/crates/edgezero-core/src/context.rs similarity index 100% rename from crates/anyedge-core/src/context.rs rename to crates/edgezero-core/src/context.rs diff --git a/crates/anyedge-core/src/error.rs b/crates/edgezero-core/src/error.rs similarity index 100% rename from crates/anyedge-core/src/error.rs rename to crates/edgezero-core/src/error.rs diff --git a/crates/anyedge-core/src/extractor.rs b/crates/edgezero-core/src/extractor.rs similarity index 100% rename from crates/anyedge-core/src/extractor.rs rename to crates/edgezero-core/src/extractor.rs diff --git a/crates/anyedge-core/src/handler.rs b/crates/edgezero-core/src/handler.rs similarity index 100% rename from crates/anyedge-core/src/handler.rs rename to crates/edgezero-core/src/handler.rs diff --git a/crates/anyedge-core/src/http.rs b/crates/edgezero-core/src/http.rs similarity index 100% rename from crates/anyedge-core/src/http.rs rename to crates/edgezero-core/src/http.rs diff --git a/crates/anyedge-core/src/lib.rs b/crates/edgezero-core/src/lib.rs similarity index 89% rename from crates/anyedge-core/src/lib.rs rename to crates/edgezero-core/src/lib.rs index 7f78f40..2af1b9c 100644 --- a/crates/anyedge-core/src/lib.rs +++ b/crates/edgezero-core/src/lib.rs @@ -16,4 +16,4 @@ pub mod responder; pub mod response; pub mod router; -pub use anyedge_macros::{action, app}; +pub use edgezero_macros::{action, app}; diff --git a/crates/anyedge-core/src/manifest.rs b/crates/edgezero-core/src/manifest.rs similarity index 99% rename from crates/anyedge-core/src/manifest.rs rename to crates/edgezero-core/src/manifest.rs index 7d2a022..eb7ae81 100644 --- a/crates/anyedge-core/src/manifest.rs +++ b/crates/edgezero-core/src/manifest.rs @@ -13,10 +13,10 @@ pub struct ManifestLoader { impl ManifestLoader { pub fn load_from_str(contents: &str) -> Self { let mut manifest: Manifest = - toml::from_str(contents).expect("anyedge manifest should be valid"); + toml::from_str(contents).expect("edgezero manifest should be valid"); manifest .validate() - .expect("anyedge manifest failed validation"); + .expect("edgezero manifest failed validation"); manifest.finalize(); Self { manifest: Arc::new(manifest), diff --git a/crates/anyedge-core/src/middleware.rs b/crates/edgezero-core/src/middleware.rs similarity index 100% rename from crates/anyedge-core/src/middleware.rs rename to crates/edgezero-core/src/middleware.rs diff --git a/crates/anyedge-core/src/params.rs b/crates/edgezero-core/src/params.rs similarity index 100% rename from crates/anyedge-core/src/params.rs rename to crates/edgezero-core/src/params.rs diff --git a/crates/anyedge-core/src/proxy.rs b/crates/edgezero-core/src/proxy.rs similarity index 100% rename from crates/anyedge-core/src/proxy.rs rename to crates/edgezero-core/src/proxy.rs diff --git a/crates/anyedge-core/src/responder.rs b/crates/edgezero-core/src/responder.rs similarity index 100% rename from crates/anyedge-core/src/responder.rs rename to crates/edgezero-core/src/responder.rs diff --git a/crates/anyedge-core/src/response.rs b/crates/edgezero-core/src/response.rs similarity index 100% rename from crates/anyedge-core/src/response.rs rename to crates/edgezero-core/src/response.rs diff --git a/crates/anyedge-core/src/router.rs b/crates/edgezero-core/src/router.rs similarity index 99% rename from crates/anyedge-core/src/router.rs rename to crates/edgezero-core/src/router.rs index de7edb0..25b0b38 100644 --- a/crates/anyedge-core/src/router.rs +++ b/crates/edgezero-core/src/router.rs @@ -17,7 +17,7 @@ use crate::middleware::{BoxMiddleware, Middleware, Next}; use crate::params::PathParams; use crate::response::IntoResponse; -pub const DEFAULT_ROUTE_LISTING_PATH: &str = "/__anyedge/routes"; +pub const DEFAULT_ROUTE_LISTING_PATH: &str = "/__edgezero/routes"; #[derive(Clone, Debug)] pub struct RouteInfo { diff --git a/crates/anyedge-macros/Cargo.toml b/crates/edgezero-macros/Cargo.toml similarity index 94% rename from crates/anyedge-macros/Cargo.toml rename to crates/edgezero-macros/Cargo.toml index d443919..4eb6527 100644 --- a/crates/anyedge-macros/Cargo.toml +++ b/crates/edgezero-macros/Cargo.toml @@ -1,5 +1,5 @@ [package] -name = "anyedge-macros" +name = "edgezero-macros" edition = { workspace = true } version = { workspace = true } authors = { workspace = true } diff --git a/crates/anyedge-macros/src/action.rs b/crates/edgezero-macros/src/action.rs similarity index 80% rename from crates/anyedge-macros/src/action.rs rename to crates/edgezero-macros/src/action.rs index 60388f7..4a2bf0b 100644 --- a/crates/anyedge-macros/src/action.rs +++ b/crates/edgezero-macros/src/action.rs @@ -72,7 +72,7 @@ pub(crate) fn expand_action_impl( let var_ident = format_ident!("__arg{}", index); extract_stmts.push(quote! { - let #var_ident = <#ty as ::anyedge_core::extractor::FromRequest>::from_request(&__ctx).await?; + let #var_ident = <#ty as ::edgezero_core::extractor::FromRequest>::from_request(&__ctx).await?; }); arg_idents.push(quote! { #var_ident }); } @@ -82,11 +82,11 @@ pub(crate) fn expand_action_impl( #(#attrs)* #vis async fn #ident( - __ctx: ::anyedge_core::context::RequestContext, - ) -> ::std::result::Result<::anyedge_core::http::Response, ::anyedge_core::error::EdgeError> { + __ctx: ::edgezero_core::context::RequestContext, + ) -> ::std::result::Result<::edgezero_core::http::Response, ::edgezero_core::error::EdgeError> { #(#extract_stmts)* let result = #inner_ident(#(#arg_idents),*).await; - ::anyedge_core::responder::Responder::respond(result) + ::edgezero_core::responder::Responder::respond(result) } }; @@ -175,10 +175,10 @@ mod tests { #[test] fn wraps_async_function() { let input = quote! { - async fn demo(ctx: ::anyedge_core::context::RequestContext) -> ::anyedge_core::http::Response { - ::anyedge_core::http::response_builder() - .status(::anyedge_core::http::StatusCode::OK) - .body(::anyedge_core::body::Body::empty()) + async fn demo(ctx: ::edgezero_core::context::RequestContext) -> ::edgezero_core::http::Response { + ::edgezero_core::http::response_builder() + .status(::edgezero_core::http::StatusCode::OK) + .body(::edgezero_core::body::Body::empty()) .unwrap() } }; @@ -202,7 +202,7 @@ mod tests { #[test] fn rejects_attribute_arguments() { let input = quote! { - async fn demo(ctx: ::anyedge_core::context::RequestContext) -> ::anyedge_core::http::Response { + async fn demo(ctx: ::edgezero_core::context::RequestContext) -> ::edgezero_core::http::Response { unimplemented!() } }; @@ -214,7 +214,7 @@ mod tests { #[test] fn rejects_self_receivers() { let input = quote! { - async fn invalid(&self) -> ::anyedge_core::http::Response { + async fn invalid(&self) -> ::edgezero_core::http::Response { unimplemented!() } }; @@ -227,15 +227,15 @@ mod tests { fn allows_request_context_argument() { let input = quote! { async fn with_ctx( - ctx: ::anyedge_core::context::RequestContext + ctx: ::edgezero_core::context::RequestContext ) -> ::std::result::Result< - ::anyedge_core::http::Response, - ::anyedge_core::error::EdgeError + ::edgezero_core::http::Response, + ::edgezero_core::error::EdgeError > { let _ = ctx; - Ok(::anyedge_core::http::response_builder() - .status(::anyedge_core::http::StatusCode::OK) - .body(::anyedge_core::body::Body::empty()) + Ok(::edgezero_core::http::response_builder() + .status(::edgezero_core::http::StatusCode::OK) + .body(::edgezero_core::body::Body::empty()) .unwrap()) } }; @@ -249,15 +249,15 @@ mod tests { fn allows_request_context_tuple_pattern_argument() { let input = quote! { async fn tuple_ctx( - RequestContext(ctx): ::anyedge_core::context::RequestContext + RequestContext(ctx): ::edgezero_core::context::RequestContext ) -> ::std::result::Result< - ::anyedge_core::http::Response, - ::anyedge_core::error::EdgeError + ::edgezero_core::http::Response, + ::edgezero_core::error::EdgeError > { let _ = ctx; - Ok(::anyedge_core::http::response_builder() - .status(::anyedge_core::http::StatusCode::OK) - .body(::anyedge_core::body::Body::empty()) + Ok(::edgezero_core::http::response_builder() + .status(::edgezero_core::http::StatusCode::OK) + .body(::edgezero_core::body::Body::empty()) .unwrap()) } }; @@ -271,8 +271,8 @@ mod tests { fn rejects_multiple_request_context_arguments() { let input = quote! { async fn invalid( - first: ::anyedge_core::context::RequestContext, - second: ::anyedge_core::context::RequestContext, + first: ::edgezero_core::context::RequestContext, + second: ::edgezero_core::context::RequestContext, ) {} }; let output = expand_action_impl(TokenStream::new(), input); @@ -284,8 +284,8 @@ mod tests { 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 { + RequestContext(a, b): ::edgezero_core::context::RequestContext + ) -> ::edgezero_core::http::Response { unimplemented!() } }; @@ -299,11 +299,11 @@ mod tests { let input = quote! { async fn demo( value: demo::ExtractorType - ) -> ::anyedge_core::http::Response { + ) -> ::edgezero_core::http::Response { let _ = value; - ::anyedge_core::http::response_builder() - .status(::anyedge_core::http::StatusCode::OK) - .body(::anyedge_core::body::Body::empty()) + ::edgezero_core::http::response_builder() + .status(::edgezero_core::http::StatusCode::OK) + .body(::edgezero_core::body::Body::empty()) .unwrap() } }; diff --git a/crates/anyedge-macros/src/app.rs b/crates/edgezero-macros/src/app.rs similarity index 91% rename from crates/anyedge-macros/src/app.rs rename to crates/edgezero-macros/src/app.rs index 5b09a3e..e5f7289 100644 --- a/crates/anyedge-macros/src/app.rs +++ b/crates/edgezero-macros/src/app.rs @@ -11,7 +11,7 @@ use syn::{parse_macro_input, Ident, LitStr, Token}; mod manifest_definitions { include!(concat!( env!("CARGO_MANIFEST_DIR"), - "/../anyedge-core/src/manifest.rs" + "/../edgezero-core/src/manifest.rs" )); } use manifest_definitions::Manifest; @@ -33,7 +33,7 @@ pub fn expand_app(input: TokenStream) -> TokenStream { .app .name .clone() - .unwrap_or_else(|| "AnyEdge App".to_string()); + .unwrap_or_else(|| "EdgeZero App".to_string()); let app_name_lit = LitStr::new(&app_name, Span::call_site()); let middleware_tokens = build_middleware_tokens(&manifest); @@ -42,8 +42,8 @@ pub fn expand_app(input: TokenStream) -> TokenStream { let output = quote! { pub struct #app_ident; - impl anyedge_core::app::Hooks for #app_ident { - fn routes() -> anyedge_core::router::RouterService { + impl edgezero_core::app::Hooks for #app_ident { + fn routes() -> edgezero_core::router::RouterService { build_router() } @@ -52,8 +52,8 @@ pub fn expand_app(input: TokenStream) -> TokenStream { } } - pub fn build_router() -> anyedge_core::router::RouterService { - let mut builder = anyedge_core::router::RouterService::builder(); + pub fn build_router() -> edgezero_core::router::RouterService { + let mut builder = edgezero_core::router::RouterService::builder(); #(#middleware_tokens)* #(#route_tokens)* builder.build() @@ -138,7 +138,7 @@ fn route_for_method(method: &str, path: &LitStr, handler: &syn::ExprPath) -> Tok quote! { builder = builder.route( #path, - anyedge_core::http::Method::from_bytes(#method_bytes) + edgezero_core::http::Method::from_bytes(#method_bytes) .expect("invalid HTTP method in manifest"), #handler, ); diff --git a/crates/anyedge-macros/src/lib.rs b/crates/edgezero-macros/src/lib.rs similarity index 100% rename from crates/anyedge-macros/src/lib.rs rename to crates/edgezero-macros/src/lib.rs diff --git a/docs/adapter-contract.md b/docs/adapter-contract.md index 0c96077..da35df7 100644 --- a/docs/adapter-contract.md +++ b/docs/adapter-contract.md @@ -1,30 +1,31 @@ # Provider Adapter Contract -This document defines the expectations AnyEdge places on provider adapters. The +This document defines the expectations EdgeZero places on provider adapters. The current implementations (Fastly Compute@Edge and Cloudflare Workers) satisfy these rules; new targets should follow the same contract so that the shared -`anyedge-core` services behave consistently. +`edgezero-core` services behave consistently. ## Goals Adapters translate provider-specific HTTP primitives into the portable `App` -in `anyedge-core`. They must preserve request semantics, stream responses +in `edgezero-core`. They must preserve request semantics, stream responses without buffering, expose provider context, and offer a proxy bridge so handlers can forward traffic without knowing which platform they are on. ## Request conversion Each adapter exposes an `into_core_request` helper that accepts the provider's -request type and returns `anyedge_core::http::Request`. The conversion must: -- Preserve the HTTP method exactly (`GET`, `POST`, etc.). +request type and returns `edgezero_core::http::Request`. The conversion must: + +- Preserve the HTTP method exactly (`GET`, `POST`, etc.). - Parse the full URI (path and query string) into an `http::Uri`. Reject invalid - URIs with `EdgeError::bad_request`. + URIs with `EdgeError::bad_request`. - Copy all headers into the core request. Provider-specific headers may be filtered only when they clash with the platform defaults (e.g. Fastly's host - override). -- Consume the request body into an `anyedge_core::body::Body`. If the provider offers + override). +- Consume the request body into an `edgezero_core::body::Body`. If the provider offers a streaming API, it should be exposed via `Body::Stream`; otherwise a single - buffered chunk is acceptable. + buffered chunk is acceptable. - Insert a provider context struct (e.g. `FastlyRequestContext`) into the request extensions. The context should expose metadata such as client IP addresses or environment handles so handlers can reach platform APIs. @@ -32,21 +33,23 @@ request type and returns `anyedge_core::http::Request`. The conversion must: ## Response conversion Adapters also expose `from_core_response` (or equivalent) to transform an -`anyedge_core::http::Response` into the provider response type. Implementations must: -- Map HTTP status codes verbatim. -- Copy headers, respecting casing rules enforced by the provider. +`edgezero_core::http::Response` into the provider response type. Implementations must: + +- Map HTTP status codes verbatim. +- Copy headers, respecting casing rules enforced by the provider. - Preserve streaming bodies. `Body::Stream` should be written chunk-by-chunk to - the provider output without buffering the entire payload. + the provider output without buffering the entire payload. - Handle encoding helpers (`decode_gzip_stream`, `decode_brotli_stream`) where a provider requires transparent decompression. ## Dispatch helper Adapters surface a `dispatch` function that bridges from the provider event loop -into the shared router (`App::router().oneshot(...)`). It should: -1. Convert the incoming provider request with `into_core_request`. -2. Await the router future. -3. Convert the resulting `Response` back into the provider type. +into the shared router (`App::router().oneshot(...)`). It should: + +1. Convert the incoming provider request with `into_core_request`. +2. Await the router future. +3. Convert the resulting `Response` back into the provider type. 4. Map any `EdgeError` into the provider's error type so failures surface as HTTP 5xx responses instead of panicking. @@ -55,15 +58,16 @@ platform-specific main functions. ## Proxy integration -Adapters implement `anyedge_core::proxy::ProxyClient` so handlers can forward outbound -requests. The client must: -- Accept a `ProxyRequest` created with `ProxyRequest::from_request`. +Adapters implement `edgezero_core::proxy::ProxyClient` so handlers can forward outbound +requests. The client must: + +- Accept a `ProxyRequest` created with `ProxyRequest::from_request`. - Build and send an outbound provider request, reusing headers and streaming the - body without buffering. + body without buffering. - Convert the provider response into a `ProxyResponse`, again preserving - streaming behaviour and normalising encodings. -- Attach a diagnostic header (e.g. `x-anyedge-proxy`) identifying which adapter - forwarded the call. + streaming behaviour and normalising encodings. +- Attach a diagnostic header (e.g. `x-edgezero-proxy`) identifying which adapter + forwarded the call. - Surface provider errors as `EdgeError::internal` so applications can decide how to respond. @@ -80,8 +84,8 @@ To keep the contract enforceable, each adapter includes integration tests that validate request/response conversions and the dispatch helper. Fastly and Cloudflare now ship `tests/contract.rs` suites that exercise: -- `into_core_request` for method, URI, header, body, and context propagation. -- `from_core_response` for status propagation and streamed body writes. +- `into_core_request` for method, URI, header, body, and context propagation. +- `from_core_response` for status propagation and streamed body writes. - `dispatch` for routed handlers, body passthrough, and streaming responses. Because the Fastly SDK links against the Compute@Edge host functions, the @@ -89,7 +93,7 @@ contract tests compile only for `wasm32-wasip1`. Run them with: ```bash rustup target add wasm32-wasip1 # once per workstation -cargo test -p anyedge-adapter-fastly --features fastly --target wasm32-wasip1 --tests +cargo test -p edgezero-adapter-fastly --features fastly --target wasm32-wasip1 --tests ``` Provide a Wasm runner (Wasmtime or Viceroy) via @@ -97,12 +101,12 @@ Provide a Wasm runner (Wasmtime or Viceroy) via of running `--no-run`. Cloudflare's adapter relies on `wasm32-unknown-unknown`. The contract suite lives -in `crates/anyedge-adapter-cloudflare/tests/contract.rs` and uses +in `crates/edgezero-adapter-cloudflare/tests/contract.rs` and uses `wasm-bindgen-test` to run under the Workers runtime shims. Execute it with: ```bash rustup target add wasm32-unknown-unknown # once per workstation -cargo test -p anyedge-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown --tests +cargo test -p edgezero-adapter-cloudflare --features cloudflare --target wasm32-unknown-unknown --tests ``` Configure a wasm-bindgen test runner via `wasm-bindgen-test-runner` (Node.js) or @@ -113,16 +117,16 @@ response, and streaming guarantees as the Fastly tests. When bringing up another adapter: -1. Implement request/response conversion functions that follow the rules above. +1. Implement request/response conversion functions that follow the rules above. 2. Provide a context type exposing the adapter's metadata and insert it in - `into_core_request`. -3. Implement a `dispatch` wrapper plus logging helper. -4. Wire up a `ProxyClient` that streams bodies and normalises encodings. + `into_core_request`. +3. Implement a `dispatch` wrapper plus logging helper. +4. Wire up a `ProxyClient` that streams bodies and normalises encodings. 5. Copy the contract test suite, swapping in the new adapter types. Ensure the tests are gated to the target architecture if the adapter SDK does not - compile for native hosts. -6. Register the adapter with `anyedge-adapter::register_adapter` (typically in a + compile for native hosts. +6. Register the adapter with `edgezero-adapter::register_adapter` (typically in a `cli` module using the `ctor` crate) so the CLI can discover it dynamically. -Adapters that fulfil these steps can be dropped into the AnyEdge CLI without +Adapters that fulfil these steps can be dropped into the EdgeZero CLI without requiring changes to application code. diff --git a/docs/manifest.md b/docs/manifest.md index 3e94a1b..3ead92f 100644 --- a/docs/manifest.md +++ b/docs/manifest.md @@ -1,8 +1,8 @@ -# anyedge.toml Manifest +# edgezero.toml Manifest -The `anyedge.toml` file describes an AnyEdge application, mirroring the +The `edgezero.toml` file describes an EdgeZero application, mirroring the ergonomics of Spin's manifest while remaining provider agnostic. New workspaces -scaffolded with `anyedge new` now include this manifest by default. +scaffolded with `edgezero new` now include this manifest by default. ## Top-level structure @@ -12,7 +12,7 @@ name = "demo" version = "0.1.0" kind = "http" entry = "crates/demo-core" -middleware = ["anyedge_core::middleware::RequestLogger"] +middleware = ["edgezero_core::middleware::RequestLogger"] [[triggers.http]] id = "root" @@ -75,7 +75,7 @@ level = "info" Metadata about the application: the display name, the crate that exposes the router (`entry`), and an optional `middleware = ["path::to::Middleware"]` list of zero-argument constructors that are registered before routes are added. Each entry must resolve to a type or function -implementing `anyedge_core::middleware::Middleware`, letting global behaviour (logging, CORS, auth guards, +implementing `edgezero_core::middleware::Middleware`, letting global behaviour (logging, CORS, auth guards, etc.) live alongside the manifest instead of being hard-wired in Rust. ### `app.middleware` @@ -88,7 +88,7 @@ in order before the request is handed to route handlers. For example: name = "app-demo" entry = "crates/app-demo-core" middleware = [ - "anyedge_core::middleware::RequestLogger", + "edgezero_core::middleware::RequestLogger", "app_demo_core::cors::Cors" ] ``` @@ -101,7 +101,7 @@ implements `Middleware`. Defines HTTP routes and their handlers. Fields: - `id`: Stable identifier for the route (optional but useful for tooling). -- `path`: URI template understood by `anyedge-core`. +- `path`: URI template understood by `edgezero-core`. - `methods`: Allowed HTTP methods (defaults to `GET` if omitted). - `handler`: Path to the handler function (for reference/documentation). - `adapters`: Which adapters expose the route. Empty means “all adapters”. @@ -112,7 +112,7 @@ Defines HTTP routes and their handlers. Fields: Declares environment variables and secrets shared across adapters. Each entry supports a human-friendly description, the upstream environment key (`env`, defaulting to the `name`), an optional default `value`, and a provider filter. -When running provider commands through `anyedge-cli`, variables with a default +When running provider commands through `edgezero-cli`, variables with a default `value` are injected into the child process and secrets must already be present in the environment; missing secrets will cause the command to abort with a helpful error message. @@ -126,7 +126,7 @@ Describes how a provider adapter is built and invoked. - `[adapters..build]`: Build target, profile, and optional feature list. - `[adapters..commands]`: Convenience commands for build/serve/deploy. -The AnyEdge CLI will, when present, run these commands for `build`, `serve`, +The EdgeZero CLI will, when present, run these commands for `build`, `serve`, and `deploy` before falling back to the adapter's built-in behaviour. That lets you customise provider tooling (e.g. add flags) without recompiling the CLI. @@ -145,7 +145,7 @@ adapters can obtain provider-specific settings via level while leaving optional values available for provider-specific defaults at runtime. -Manifest parsing lives in `anyedge-core::manifest`, and CLI commands now verify +Manifest parsing lives in `edgezero-core::manifest`, and CLI commands now verify that a provider is declared before invoking adapter-specific tooling. Additional provider metadata (extra environment bindings, secrets per provider, extra commands) can be layered under these sections without breaking existing tooling @@ -155,30 +155,30 @@ thanks to permissive deserialisation defaults. and handlers, well-formed logging levels, etc.) so mistakes are caught early at startup or during macro expansion. -`anyedge-core::ManifestLoader` provides a shared parser so applications can load +`edgezero-core::ManifestLoader` provides a shared parser so applications can load the manifest at runtime. The demo app uses this loader to build its router from the manifest, and the CLI reuses the same types when executing provider commands. ## CLI integration -`anyedge build|serve|deploy --adapter ` looks up the provider entry in -`anyedge.toml`. If a `[adapters..commands]` block supplies a `build`, +`edgezero build|serve|deploy --adapter ` looks up the provider entry in +`edgezero.toml`. If a `[adapters..commands]` block supplies a `build`, `serve`, or `deploy` command, the CLI executes it from the manifest directory. This allows each adapter to decide how artifacts are produced (for example, invoking `cargo build --target wasm32-wasip1` for Fastly or `wrangler dev` for Cloudflare). When commands are omitted, the CLI falls back to the built-in helpers shipped with the adapters (currently the Fastly adapter). -The example app under `examples/app-demo` ships an `anyedge.toml` manifest that +The example app under `examples/app-demo` ships an `edgezero.toml` manifest that drives both runtime routing and CLI commands. `app-demo-core` reads the manifest at startup to register HTTP routes (rather than hard-coding paths in Rust), and -running `anyedge build --adapter fastly` from the workspace root invokes the +running `edgezero build --adapter fastly` from the workspace root invokes the Fastly build command specified in the manifest. ## Generating routers via macro -Use `anyedge_core::app!("path/to/anyedge.toml", AppName);` inside your +Use `edgezero_core::app!("path/to/edgezero.toml", AppName);` inside your crate to generate a `Hooks` implementation and `build_router` function directly from the manifest. The `AppName` argument is optional; when omitted the macro emits a struct named `App`. The macro understands the HTTP trigger list (including @@ -190,7 +190,7 @@ shows the minimal usage: ```rust mod handlers; -anyedge_core::app!("../../anyedge.toml"); +edgezero_core::app!("../../edgezero.toml"); ``` Handlers referenced in the manifest can therefore use either `crate::` or the diff --git a/examples/app-demo/Cargo.lock b/examples/app-demo/Cargo.lock index 0dbec8a..5c24751 100644 --- a/examples/app-demo/Cargo.lock +++ b/examples/app-demo/Cargo.lock @@ -50,101 +50,6 @@ 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", - "bytes", - "flate2", - "futures", - "futures-util", - "log", - "wasm-bindgen-test", - "worker", -] - -[[package]] -name = "anyedge-adapter-fastly" -version = "0.1.0" -dependencies = [ - "anyedge-core", - "async-stream", - "async-trait", - "brotli", - "bytes", - "chrono", - "fastly", - "fern", - "flate2", - "futures", - "futures-util", - "log", - "log-fastly", -] - -[[package]] -name = "anyedge-core" -version = "0.1.0" -dependencies = [ - "anyedge-macros", - "anyhow", - "async-compression", - "async-stream", - "async-trait", - "bytes", - "futures", - "futures-util", - "http", - "http-body", - "log", - "matchit 0.8.4", - "serde", - "serde_json", - "serde_urlencoded", - "thiserror 2.0.16", - "toml", - "tower-service", - "tracing", - "validator", -] - -[[package]] -name = "anyedge-macros" -version = "0.1.0" -dependencies = [ - "log", - "proc-macro2", - "quote", - "serde", - "syn 2.0.106", - "toml", - "validator", -] - [[package]] name = "anyhow" version = "1.0.99" @@ -155,11 +60,11 @@ checksum = "b0674a1ddeecb70197781e945de4b3b8ffb61fa939a5597bcf48503737663100" name = "app-demo-adapter-axum" version = "0.1.0" dependencies = [ - "anyedge-adapter-axum", - "anyedge-core", "anyhow", "app-demo-core", "axum 0.7.9", + "edgezero-adapter-axum", + "edgezero-core", "log", "simple_logger 4.3.3", "tokio", @@ -170,9 +75,9 @@ dependencies = [ name = "app-demo-adapter-cloudflare" version = "0.1.0" dependencies = [ - "anyedge-adapter-cloudflare", - "anyedge-core", "app-demo-core", + "edgezero-adapter-cloudflare", + "edgezero-core", "worker", ] @@ -180,9 +85,9 @@ dependencies = [ name = "app-demo-adapter-fastly" version = "0.1.0" dependencies = [ - "anyedge-adapter-fastly", - "anyedge-core", "app-demo-core", + "edgezero-adapter-fastly", + "edgezero-core", "fastly", "log", "once_cell", @@ -192,8 +97,9 @@ dependencies = [ name = "app-demo-core" version = "0.1.0" dependencies = [ - "anyedge-core", + "async-trait", "bytes", + "edgezero-core", "futures", "serde", "serde_json", @@ -606,6 +512,101 @@ version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +[[package]] +name = "edgezero-adapter-axum" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-trait", + "axum 0.8.6", + "bytes", + "edgezero-core", + "futures", + "futures-util", + "http", + "log", + "reqwest", + "simple_logger 5.1.0", + "thiserror 2.0.16", + "tokio", + "tower", + "tracing", +] + +[[package]] +name = "edgezero-adapter-cloudflare" +version = "0.1.0" +dependencies = [ + "async-trait", + "brotli", + "bytes", + "edgezero-core", + "flate2", + "futures", + "futures-util", + "log", + "wasm-bindgen-test", + "worker", +] + +[[package]] +name = "edgezero-adapter-fastly" +version = "0.1.0" +dependencies = [ + "async-stream", + "async-trait", + "brotli", + "bytes", + "chrono", + "edgezero-core", + "fastly", + "fern", + "flate2", + "futures", + "futures-util", + "log", + "log-fastly", +] + +[[package]] +name = "edgezero-core" +version = "0.1.0" +dependencies = [ + "anyhow", + "async-compression", + "async-stream", + "async-trait", + "bytes", + "edgezero-macros", + "futures", + "futures-util", + "http", + "http-body", + "log", + "matchit 0.9.0", + "serde", + "serde_json", + "serde_urlencoded", + "thiserror 2.0.16", + "toml", + "tower-service", + "tracing", + "validator", +] + +[[package]] +name = "edgezero-macros" +version = "0.1.0" +dependencies = [ + "log", + "proc-macro2", + "quote", + "serde", + "syn 2.0.106", + "toml", + "validator", +] + [[package]] name = "either" version = "1.15.0" @@ -1228,6 +1229,12 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" +[[package]] +name = "matchit" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ea5f97102eb9e54ab99fb70bb175589073f554bdadfb74d9bd656482ea73e2a" + [[package]] name = "memchr" version = "2.7.5" @@ -1460,7 +1467,7 @@ dependencies = [ "once_cell", "socket2", "tracing", - "windows-sys 0.59.0", + "windows-sys 0.60.2", ] [[package]] @@ -2407,7 +2414,7 @@ version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" dependencies = [ - "windows-sys 0.59.0", + "windows-sys 0.61.2", ] [[package]] diff --git a/examples/app-demo/Cargo.toml b/examples/app-demo/Cargo.toml index 4e40650..c8ca37c 100644 --- a/examples/app-demo/Cargo.toml +++ b/examples/app-demo/Cargo.toml @@ -8,21 +8,22 @@ members = [ resolver = "2" [workspace.dependencies] -anyedge-adapter-cloudflare = { path = "../../crates/anyedge-adapter-cloudflare" } -anyedge-adapter-fastly = { path = "../../crates/anyedge-adapter-fastly" } -anyedge-adapter-axum = { path = "../../crates/anyedge-adapter-axum" } -anyedge-core = { path = "../../crates/anyedge-core" } -app-demo-core = { path = "crates/app-demo-core" } anyhow = "1" +app-demo-core = { path = "crates/app-demo-core" } +async-trait = "0.1" axum = "0.7" bytes = "1" +edgezero-adapter-axum = { path = "../../crates/edgezero-adapter-axum" } +edgezero-adapter-cloudflare = { path = "../../crates/edgezero-adapter-cloudflare" } +edgezero-adapter-fastly = { path = "../../crates/edgezero-adapter-fastly" } +edgezero-core = { path = "../../crates/edgezero-core" } fastly = "0.11" futures = { version = "0.3", default-features = false, features = ["std", "executor"] } log = "0.4" once_cell = "1" -simple_logger = "4" serde = { version = "1", features = ["derive"] } serde_json = "1" +simple_logger = "4" tokio = { version = "1", features = ["macros", "rt-multi-thread"] } tracing = "0.1" worker = { version = "0.6", default-features = false, features = ["http"] } diff --git a/examples/app-demo/crates/app-demo-adapter-axum/Cargo.toml b/examples/app-demo/crates/app-demo-adapter-axum/Cargo.toml index 8c8cfe0..977df49 100644 --- a/examples/app-demo/crates/app-demo-adapter-axum/Cargo.toml +++ b/examples/app-demo/crates/app-demo-adapter-axum/Cargo.toml @@ -10,9 +10,9 @@ path = "src/main.rs" [dependencies] app-demo-core = { workspace = true } -anyedge-core = { workspace = true } +edgezero-core = { workspace = true } anyhow = { workspace = true } -anyedge-adapter-axum = { workspace = true, features = ["axum"] } +edgezero-adapter-axum = { workspace = true, features = ["axum"] } axum = { workspace = true } log = { workspace = true } simple_logger = { workspace = true } diff --git a/examples/app-demo/crates/app-demo-adapter-axum/src/main.rs b/examples/app-demo/crates/app-demo-adapter-axum/src/main.rs index 9eebed6..b847962 100644 --- a/examples/app-demo/crates/app-demo-adapter-axum/src/main.rs +++ b/examples/app-demo/crates/app-demo-adapter-axum/src/main.rs @@ -1,7 +1,8 @@ use app_demo_core::App; fn main() { - if let Err(err) = anyedge_adapter_axum::run_app::(include_str!("../../../anyedge.toml")) { + if let Err(err) = edgezero_adapter_axum::run_app::(include_str!("../../../edgezero.toml")) + { eprintln!("app-demo-adapter-axum failed: {err}"); std::process::exit(1); } diff --git a/examples/app-demo/crates/app-demo-adapter-cloudflare/Cargo.toml b/examples/app-demo/crates/app-demo-adapter-cloudflare/Cargo.toml index 60d6d20..0db5fe7 100644 --- a/examples/app-demo/crates/app-demo-adapter-cloudflare/Cargo.toml +++ b/examples/app-demo/crates/app-demo-adapter-cloudflare/Cargo.toml @@ -10,10 +10,10 @@ path = "src/main.rs" [features] default = ["cloudflare"] -cloudflare = ["anyedge-adapter-cloudflare/cloudflare"] +cloudflare = ["edgezero-adapter-cloudflare/cloudflare"] [dependencies] app-demo-core = { workspace = true } -anyedge-adapter-cloudflare = { workspace = true } -anyedge-core = { workspace = true } +edgezero-adapter-cloudflare = { workspace = true } +edgezero-core = { workspace = true } worker = { workspace = true } diff --git a/examples/app-demo/crates/app-demo-adapter-cloudflare/src/main.rs b/examples/app-demo/crates/app-demo-adapter-cloudflare/src/main.rs index f312b0a..abf89fe 100644 --- a/examples/app-demo/crates/app-demo-adapter-cloudflare/src/main.rs +++ b/examples/app-demo/crates/app-demo-adapter-cloudflare/src/main.rs @@ -8,7 +8,7 @@ use worker::*; #[cfg(target_arch = "wasm32")] #[event(fetch)] pub async fn main(req: Request, env: Env, ctx: Context) -> Result { - anyedge_adapter_cloudflare::run_app::(req, env, ctx).await + edgezero_adapter_cloudflare::run_app::(req, env, ctx).await } #[cfg(not(target_arch = "wasm32"))] diff --git a/examples/app-demo/crates/app-demo-adapter-fastly/Cargo.toml b/examples/app-demo/crates/app-demo-adapter-fastly/Cargo.toml index 5aad171..7896ac8 100644 --- a/examples/app-demo/crates/app-demo-adapter-fastly/Cargo.toml +++ b/examples/app-demo/crates/app-demo-adapter-fastly/Cargo.toml @@ -10,15 +10,15 @@ path = "src/main.rs" [features] default = [] -fastly = ["anyedge-adapter-fastly/fastly"] +fastly = ["edgezero-adapter-fastly/fastly"] [dependencies] app-demo-core = { workspace = true } -anyedge-adapter-fastly = { workspace = true } +edgezero-adapter-fastly = { workspace = true } log = { workspace = true } [target.'cfg(target_arch = "wasm32")'.dependencies] -anyedge-core = { workspace = true } -anyedge-adapter-fastly = { workspace = true, features = ["fastly"] } +edgezero-core = { workspace = true } +edgezero-adapter-fastly = { workspace = true, features = ["fastly"] } fastly = { workspace = true } once_cell = { workspace = true } diff --git a/examples/app-demo/crates/app-demo-adapter-fastly/src/main.rs b/examples/app-demo/crates/app-demo-adapter-fastly/src/main.rs index a9c7ee6..da6c450 100644 --- a/examples/app-demo/crates/app-demo-adapter-fastly/src/main.rs +++ b/examples/app-demo/crates/app-demo-adapter-fastly/src/main.rs @@ -8,7 +8,7 @@ use fastly::{Error, Request, Response}; #[cfg(target_arch = "wasm32")] #[fastly::main] pub fn main(req: Request) -> Result { - anyedge_adapter_fastly::run_app::(include_str!("../../../anyedge.toml"), req) + edgezero_adapter_fastly::run_app::(include_str!("../../../edgezero.toml"), req) } #[cfg(not(target_arch = "wasm32"))] diff --git a/examples/app-demo/crates/app-demo-core/Cargo.toml b/examples/app-demo/crates/app-demo-core/Cargo.toml index a963715..d817132 100644 --- a/examples/app-demo/crates/app-demo-core/Cargo.toml +++ b/examples/app-demo/crates/app-demo-core/Cargo.toml @@ -9,7 +9,7 @@ name = "app_demo_core" path = "src/lib.rs" [dependencies] -anyedge-core = { workspace = true } +edgezero-core = { workspace = true } bytes = { workspace = true } futures = { workspace = true } serde = { workspace = true } 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 e486285..2175402 100644 --- a/examples/app-demo/crates/app-demo-core/src/handlers.rs +++ b/examples/app-demo/crates/app-demo-core/src/handlers.rs @@ -1,12 +1,12 @@ -use anyedge_core::action; -use anyedge_core::body::Body; -use anyedge_core::context::RequestContext; -use anyedge_core::error::EdgeError; -use anyedge_core::extractor::{Headers, Json, Path}; -use anyedge_core::http::{self, Response, StatusCode, Uri}; -use anyedge_core::proxy::ProxyRequest; -use anyedge_core::response::Text; use bytes::Bytes; +use edgezero_core::action; +use edgezero_core::body::Body; +use edgezero_core::context::RequestContext; +use edgezero_core::error::EdgeError; +use edgezero_core::extractor::{Headers, Json, Path}; +use edgezero_core::http::{self, Response, StatusCode, Uri}; +use edgezero_core::proxy::ProxyRequest; +use edgezero_core::response::Text; use futures::{stream, StreamExt}; const DEFAULT_PROXY_BASE: &str = "https://httpbin.org"; @@ -23,7 +23,7 @@ pub(crate) struct EchoBody { #[action] pub(crate) async fn root() -> Text<&'static str> { - Text::new("AnyEdge Demo App") + Text::new("EdgeZero Demo App") } #[action] @@ -139,15 +139,15 @@ fn proxy_not_available_response() -> Result { #[cfg(test)] mod tests { use super::*; - use anyedge_core::body::Body; - use anyedge_core::context::RequestContext; - use anyedge_core::http::header::{HeaderName, HeaderValue}; - use anyedge_core::http::{request_builder, Method, StatusCode, Uri}; - use anyedge_core::params::PathParams; - use anyedge_core::proxy::{ProxyClient, ProxyHandle, ProxyResponse}; - use anyedge_core::response::IntoResponse; - use anyedge_core::router::DEFAULT_ROUTE_LISTING_PATH; use async_trait::async_trait; + use edgezero_core::body::Body; + use edgezero_core::context::RequestContext; + use edgezero_core::http::header::{HeaderName, HeaderValue}; + use edgezero_core::http::{request_builder, Method, StatusCode, Uri}; + use edgezero_core::params::PathParams; + use edgezero_core::proxy::{ProxyClient, ProxyHandle, ProxyResponse}; + use edgezero_core::response::IntoResponse; + use edgezero_core::router::DEFAULT_ROUTE_LISTING_PATH; use futures::{executor::block_on, StreamExt}; use std::collections::HashMap; use std::env; @@ -157,7 +157,7 @@ mod tests { let ctx = empty_context("/"); let response = block_on(root(ctx)).expect("handler ok").into_response(); let bytes = response.into_body().into_bytes(); - assert_eq!(bytes.as_ref(), b"AnyEdge Demo App"); + assert_eq!(bytes.as_ref(), b"EdgeZero Demo App"); } #[test] diff --git a/examples/app-demo/crates/app-demo-core/src/lib.rs b/examples/app-demo/crates/app-demo-core/src/lib.rs index 501739c..d8939a1 100644 --- a/examples/app-demo/crates/app-demo-core/src/lib.rs +++ b/examples/app-demo/crates/app-demo-core/src/lib.rs @@ -1,3 +1,3 @@ mod handlers; -anyedge_core::app!("../../anyedge.toml"); +edgezero_core::app!("../../edgezero.toml"); diff --git a/examples/app-demo/anyedge.toml b/examples/app-demo/edgezero.toml similarity index 97% rename from examples/app-demo/anyedge.toml rename to examples/app-demo/edgezero.toml index 811f6bc..05c7a1f 100644 --- a/examples/app-demo/anyedge.toml +++ b/examples/app-demo/edgezero.toml @@ -3,7 +3,7 @@ name = "app-demo" version = "0.1.0" kind = "http" entry = "crates/app-demo-core" -middleware = ["anyedge_core::middleware::RequestLogger"] +middleware = ["edgezero_core::middleware::RequestLogger"] [[triggers.http]] id = "root" @@ -43,7 +43,7 @@ adapters = ["fastly", "cloudflare", "axum"] [[triggers.http]] id = "routes" -path = "/__anyedge/routes" +path = "/__edgezero/routes" methods = ["GET"] handler = "app_demo_core::handlers::list_routes" adapters = ["fastly", "cloudflare", "axum"] diff --git a/scripts/run_tests.sh b/scripts/run_tests.sh index 981f84e..192445e 100755 --- a/scripts/run_tests.sh +++ b/scripts/run_tests.sh @@ -34,11 +34,11 @@ section "Workspace Tests" run cargo test --workspace section "Fastly CLI Tests" -run cargo test -p anyedge-adapter-fastly --no-default-features --features cli +run cargo test -p edgezero-adapter-fastly --no-default-features --features cli section "Fastly Wasm Tests" ( - cd crates/anyedge-adapter-fastly + cd crates/edgezero-adapter-fastly run cargo test --features fastly --target wasm32-wasip1 -- --nocapture )