apollo-errors 0.7.0

Structured error handling with automatic format conversion
Documentation
# Changelog

All notable changes to **apollo-errors** will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.7.0]

### 💥 Breaking Changes

#### Configurable error formatting ([#383]https://github.com/apollographql/apollo-platform-rs/pull/383, [#384]https://github.com/apollographql/apollo-platform-rs/pull/384, [#388]https://github.com/apollographql/apollo-platform-rs/pull/388) by @DMallare

Render methods (`to_json`, `to_graphql`, `to_html`, `to_text`, `to_jsonrpc`) on `Error`, `ErrorExt`, and `HeapErrorExt` now accept `&FormatConfig`, controlling field name casing and error code format. Add `&FormatConfig::default()` to existing call sites to preserve prior behavior.

`Renderer::GraphQL` now defaults to `CamelCase` field names and `ScreamingSnakeCase` error codes. Services using `Renderer::GraphQL` will see different field names and error codes in responses unless an explicit override is set:

```rust
// Restore previous casing for GraphQL
NegotiationConfig::new()
    .with_format_config(Renderer::GraphQL, FormatConfig::default())
```

`NegotiationConfig::with_format_config` now takes a `(Renderer, FormatConfig)` pair to override the built-in default for a specific renderer:

```rust
// Before
config.with_format_config(FormatConfig {
    field_case: FieldCase::CamelCase,
    code_case: CodeCase::ScreamingSnakeCase,
})

// After
config.with_format_config(Renderer::Json, FormatConfig {
    field_case: FieldCase::CamelCase,
    code_case: CodeCase::ScreamingSnakeCase,
})
```

`FieldMetadata` and `RegularVariantMetadata` now carry pre-computed `&'static str` case variants via `name_for(FieldCase)` and `code_for(CodeCase)` accessors. `#[extension]` gains an optional `rename = "..."` argument as an absolute override for all cases.

#### Error catalog `code` field changed to `CodeMetadata` ([#393]https://github.com/apollographql/apollo-platform-rs/pull/393) by @DMallare

`ErrorVariantMetadata.code` is now `CodeMetadata` instead of `&'static str`, exposing all five pre-computed case variants:

```rust
// Before
let code: &str = variant.code;

// After
let code: &str = variant.code.default;            // original form, e.g. "config::invalid_port"
let screaming: &str = variant.code.screaming_snake; // "CONFIG_INVALID_PORT"
let camel: &str = variant.code.camel;               // "configInvalidPort"
let pascal: &str = variant.code.pascal;             // "ConfigInvalidPort"
let kebab: &str = variant.code.kebab;               // "config-invalid-port"
```

The JSON catalog representation changes accordingly: `"code"` is now an object with `default`, `screamingSnake`, `camel`, `pascal`, and `kebab` keys.

### ✨ Features

#### `#[http_status(...)]` accepts `http::StatusCode` path expressions ([#394]https://github.com/apollographql/apollo-platform-rs/pull/394) by @DMallare

```rust
// Before — integer literal only
#[http_status(404)]
NotFound,

// After — named constant also accepted
#[http_status(StatusCode::NOT_FOUND)]
NotFound,
```

Invalid paths (e.g. `StatusCode::MADE_UP`) produce a compile error. Integer literals continue to work unchanged.

#### `http_status()` returns `http::StatusCode` ([#385]https://github.com/apollographql/apollo-platform-rs/pull/385) by @DMallare

`Error::http_status()` now returns `http::StatusCode`. Invalid `#[http_status(...)]` values (outside the 100-999 range) are rejected at derive macro expansion time.

### 📚 Documentation

#### Configurable formatting guide ([#395]https://github.com/apollographql/apollo-platform-rs/pull/395) by @DMallare

`FieldCase` and `CodeCase` variants now include concrete before/after output examples in rustdoc. `NegotiationConfig::with_format_config` documents the built-in format defaults for each renderer. The book's `tower.md` chapter includes an end-to-end example rendering the same error type under JSON and GraphQL with default configuration.



## [0.6.0]

### ✨ Features

#### support `Box<dyn Error + Send + Sync>` in `#[source]` fields ([#343]https://github.com/apollographql/apollo-platform-rs/pull/343) by @BrynCooke

The derive macro now correctly boxed trait objects as error sources.



## [0.4.0]

### 💥 Breaking Changes

#### support `#[from]` attribute on transparent variants ([#270]https://github.com/apollographql/apollo-platform-rs/pull/270) by @goto-bus-stop

Apply `#[from]` to transparent variants in an error enum to generate a `From<T>` implementation:

```rust
use apollo_errors::Error;
use apollo_errors::miette;

#[derive(Debug, Error, miette::Diagnostic)]
enum AppError {
    #[error(transparent)]
    #[diagnostic(transparent)]
    Request(#[from] RequestError),
}
```

**Breaking**: using `#[source]` on a transparent variant is now an error. Previously, the attribute
would be silently ignored. A `source()` implementation is always generated for transparent variants.



## [0.3.0]

### Features

#### add http_header attribute for returning error fields as HTTP headers ([#230]https://github.com/apollographql/apollo-platform-rs/pull/230) by @BrynCooke

Error struct fields can now be annotated with `#[http_header("Header-Name")]` to
automatically include them as HTTP response headers when using the Tower middleware.

```rust
#[http_status(429)]
RateLimitExceeded {
    #[http_header("Retry-After")]
    retry_after: u64
},
```

For `Option<T>` fields, headers are only included when the value is `Some`.

**Breaking Changes**

- `Error::http_status()` now returns `http::StatusCode` instead of `u16`. Update
comparisons from `error.http_status() == 404` to
`error.http_status() == http::StatusCode::NOT_FOUND`.
- `CatalogVariantEntry.http_status` changed from `u16` to `http::StatusCode`.



## [0.2.0]

### ✨ Features

#### Implement `Default` for the `ErrorLayer`'s response type ([#171]https://github.com/apollographql/apollo-platform-rs/pull/171) by @BrynCooke

This change allows the `ErrorHandler` to be used in middleware chains that require the response type to implement `Default`.


### 🐛 Bug Fixes

#### reject optional fields in error messages ([#169]https://github.com/apollographql/apollo-platform-rs/pull/169) by @BrynCooke

Optional fields (`Option<T>`) are now rejected at compile time when referenced
in error message format strings. Since `Option<T>` does not implement `Display`,
using them in messages like `#[error("value: {field}")]` would cause confusing
compilation errors. The derive macro now provides a clear error message explaining
the issue.



## [0.1.0]

### 💥 Breaking Changes

#### use snake_case field names in JSON and GraphQL output ([#154]https://github.com/apollographql/apollo-platform-rs/pull/154) by @BrynCooke

Extension field names in JSON and GraphQL output now use their original Rust snake_case names
instead of being converted to camelCase.

## Migration

If you rely on field names in error output, update your code to use snake_case:

Before:

```json
{
  "error": "config::invalid_port",
  "message": "Invalid port",
  "configFile": "/etc/config.toml"
}
```

After:

```json
{
  "error": "config::invalid_port",
  "message": "Invalid port",
  "config_file": "/etc/config.toml"
}
```

#### remove apollo-errors-core crate and inline into apollo-errors ([#145]https://github.com/apollographql/apollo-platform-rs/pull/145) by @BrynCooke

The `apollo-errors-core` crate has been removed and its functionality inlined directly into `apollo-errors`. You can remove the `apollo-errors-core` dependency from your crates using `apollo-errors`:

```toml
[dependencies]
apollo-errors = "0.1.0"
```

In addition, many public types have been moved to private reducing the public API surface to a bare minimum.
Users that were using `apollo_errors::*Metadata*` types and `error_metadata()` fn should migrate to:

- `error_catalog()`
- `ErrorFieldMetadata`
- `ErrorMetadata`
- `ErrorVariantMetadata`


### ✨ Features

#### add JSON-RPC renderer to tower layer ([#157]https://github.com/apollographql/apollo-platform-rs/pull/157) by @BrynCooke

The tower `ErrorLayer` now supports JSON-RPC 2.0 error responses via content negotiation.

Send `Accept: application/json-rpc` to receive errors in JSON-RPC 2.0 format:

```json
{
  "jsonrpc": "2.0",
  "error": {
    "code": -32000,
    "message": "Error message",
    "data": {
      "diagnostic_code": "error::code",
      "field": "value"
    }
  },
  "id": null
}
```

The `id` field is `null` since the request ID is not available at the HTTP layer.

#### add JSON-RPC 2.0 error format support ([#152]https://github.com/apollographql/apollo-platform-rs/pull/152) by @BrynCooke

Errors can now be rendered as JSON-RPC 2.0 error objects via the `to_jsonrpc()` method. The output includes a numeric error code, message, and data object containing the diagnostic code and any extension fields.

Use the `#[jsonrpc_code(...)]` attribute to specify custom error codes. Without it, errors default to -32000 (server error). Standard JSON-RPC codes (-32700 to -32603) are supported for protocol-level errors.


### 🐛 Bug Fixes

#### fix compilation error when using Option fields in error extensions ([#164]https://github.com/apollographql/apollo-platform-rs/pull/164) by @BrynCooke

Extension fields with `Option<T>` types now compile correctly. Previously, using
`Option<T>` would fail because `Option` doesn't implement `Display`.

This applies to all output formats (JSON, GraphQL, JSON-RPC, HTML) and works
for both struct and enum error types.

#### interpolate field values in error messages ([#156]https://github.com/apollographql/apollo-platform-rs/pull/156) by @BrynCooke

Error messages now substitute `{field_name}` placeholders with actual field values.
Previously, messages like "invalid port {port}" were output literally; they now
render as "invalid port 8080".

#### remove `Sync` bound and preserve size hints in ErrorLayer ([#149]https://github.com/apollographql/apollo-platform-rs/pull/149) by @BrynCooke

The `ErrorLayer` tower middleware no longer requires the response body type to implement `Sync`. This allows the layer to work with body types that are `Send` but not `Sync`, such as those produced by some tower-http middleware.

#### remove implicit dependencies from derive macro ([#137]https://github.com/apollographql/apollo-platform-rs/pull/137) by @goto-bus-stop

The `#[derive(apollo_errors::Error)]` macro previously produced output that relied on the `linkme` and `serde_json` crates. Users had to install those crates even if they were not using them directly.

Now, the only crates that are required to use apollo-errors are `apollo-errors` and `apollo-errors-core`:

```toml
[dependencies]
apollo-errors = "0.1.0"
apollo-errors-core = "0.1.0"
```



## [0.0.1]

Initial release