# 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