Packages

Spectral provides type-driven JSON encoding/decoding, JSON Schema generation, and OpenAPI 3.1 specification generation. It uses Elixir's type system to automatically handle serialization based on struct type definitions.

Current section

Files

Jump to
spectral CHANGELOG.md
Raw

CHANGELOG.md

# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
## [0.9.2] - 2026-04-01
### Changed
- Upgraded spectra dependency to `~> 0.9.3`
- Internal: replaced O(N²) spectral pairing loop with an O(N log N) state machine — no behaviour change, compile times for large modules may improve
- README: added Configuration section documenting `spectra` application environment options
## [0.9.1] - 2026-03-26
### Fixed
- String constraint parameters (`min_length`, `max_length`, `pattern`) are now correctly enforced when the type is defined as an alias for `String.t()` — e.g. `@type slug :: String.t()` with `spectral type_parameters: %{pattern: "^[a-z]+$"}`. `format` remains a schema annotation only (not enforced at encode/decode time) but is now preserved correctly for schema generation. Previously these constraints were silently ignored at encode/decode time and omitted from schema output. Requires spectra `~> 0.9.1`.
- `Spectral.Codec.Date` and `Spectral.Codec.DateTime` now correctly handle the `:binary_string` format. They previously matched on `:binary` (which is not a valid spectra format), causing them to silently return `:continue` when called via `Spectral.encode/decode` with `:binary_string` — the correct format for path variables and query parameters.
### Changed
- Upgraded spectra dependency to `~> 0.9.1`
- README: corrected all encode/decode examples to use explicit `:json` format argument; updated codec callback signatures to 6-arg form; improved section headings and structure
## [0.9.0] - 2026-03-25
### Added
- `Spectral.Type` module with `type_args/1` — extracts concrete type-variable bindings from the `sp_type` argument passed to codec callbacks, enabling codecs to recursively encode/decode generic types
- `deprecated` is now a documented `spectral` field for types — marks a type as deprecated, emitted as `"deprecated": true` in the generated JSON Schema
- `examples_function` added to the `spectral/1` macro `@doc` and `use Spectral` moduledoc
### Changed
- **BREAKING**: `Spectral.Codec` callbacks changed from 5-arg to 6-arg. A new `sp_type` argument is inserted as the 5th argument (before `params`) in `encode/6`, `decode/6`, and `schema/5`. Update all codec implementations by adding a `_sp_type` parameter before `params` in every callback clause.
- `Spectral.Codec.MapSet` for `MapSet.t(elem)` now recursively encodes, decodes, and generates schemas for each element according to its type, using `Spectral.Type.type_args/1`
- `spectral/1` macro `@doc` split into separate `@type` and `@spec` field sections, so function spec fields (`summary`, `description`, `deprecated`) are now documented on the macro itself
- Upgraded spectra dependency to `~> 0.9.0`
## [0.8.1] - 2026-03-21
### Added
- `Spectral.schema/4` — accepts an options list as the last argument, supporting the `:pre_encoded` option to return a map instead of iodata
- `Spectral.OpenAPI.endpoints_to_openapi/3` — accepts an options list, supporting the same `:pre_encoded` option
- `schema_option/0` type for the new options
### Changed
- Upgraded spectra dependency from `~> 0.8.0` to `~> 0.8.1`
- `Spectral.OpenAPI` specs now use precise exported spectra types (`endpoint_spec`, `response_spec`, `openapi_metadata`, etc.) instead of `dynamic()` / `map()`
- README revised: requirements merged into installation, sections reordered, Options table added, string/binary constraints documented, `examples_function` documented
## [0.8.0] - 2026-03-19
### Added
- `Spectral.Codec` behaviour for custom serialization/deserialization — implement `encode/5`, `decode/5`, and optionally `schema/4` to handle any type
- Built-in codecs for common Elixir types: `Spectral.Codec.DateTime`, `Spectral.Codec.Date`, and `Spectral.Codec.MapSet`
- `type_parameters` key in `spectral` attribute — passes a static value to codec callbacks as the `params` argument, enabling one codec to handle multiple type variants
### Changed
- **BREAKING**: `Spectral.OpenAPI.with_request_body/4` — the fourth argument reverted from an opts map back to a `content_type :: binary()` string; description is now sourced automatically from the type's `spectral` attribute. Update calls from `with_request_body(e, mod, schema, %{content_type: "application/xml"})` to `with_request_body(e, mod, schema, "application/xml")`.
- Upgraded spectra dependency to `~> 0.8.0`
### Removed
- **BREAKING**: `Spectral.TypeInfo.new/0` removed — use `new(module, false)` instead
## [0.7.0] - 2026-03-04
### Added
- `Spectral.OpenAPI.with_request_body/4` now accepts an opts map as the fourth argument with optional `content_type` and `description` keys
- `parameter_spec` in `Spectral.OpenAPI.with_parameter/3` now supports `description` and `deprecated` fields
- `header_spec` in `Spectral.OpenAPI.response_with_header/4` now supports a `deprecated` field
- `endpoints_to_openapi/2` metadata now supports additional `info` fields (`summary`, `description`, `terms_of_service`, `contact`, `license`) and a top-level `servers` list
### Changed
- **BREAKING**: `Spectral.OpenAPI.with_request_body/4` — the fourth argument changed from a `content_type :: binary()` string to an `opts :: map()`. Update calls from `with_request_body(e, mod, schema, "application/xml")` to `with_request_body(e, mod, schema, %{content_type: "application/xml"})`.
- Upgraded spectra dependency from `~> 0.6.0` to `~> 0.7.0`
## [0.6.0] - 2026-03-04
### Added
- `spectral/1` macro can now be placed before `@spec` definitions to attach endpoint documentation (`summary`, `description`, `deprecated`) to functions
- `Spectral.TypeInfo.get_function_doc/3` — retrieves endpoint documentation stored in a function's `sp_function_spec` metadata; returns `{:ok, doc}`, `{:error, :no_doc_found}`, or `{:error, :function_not_found}`
- `Spectral.OpenAPI.endpoint/5` — 5-argument overload that reads a function's `spectral/1` metadata from the module's type info and uses it as the OpenAPI operation documentation; raises `ArgumentError` if the function has no `spectral/1` annotation
### Changed
- Upgraded spectra dependency from `~> 0.5.1` to `~> 0.6.0`
- spectra 0.6.0 fixes the `sp_union` record default value (no user-facing impact)
## [0.5.1] - 2026-03-02
### Added
- `opts` parameter to `encode/5`, `decode/5`, `encode!/5`, and `decode!/5` for passing options to the underlying spectra library (backward-compatible: defaults to `[]`)
- `:pre_encoded` option for `encode/5`/`encode!/5`: returns intermediate JSON term (map/list) instead of iodata
- `:pre_decoded` option for `decode/5`/`decode!/5`: accepts an already-decoded JSON term as input, skipping JSON parsing
### Changed
- Upgraded spectra dependency from 0.5.0 to 0.5.1
- spectra 0.5.1 adds performance improvements via `persistent_term` caching for `__spectra_type_info__/0` calls
## [0.5.0] - 2026-02-26
### Added
- `spectral/1` annotation macro for documenting `@type`/`@typep` definitions with JSON Schema metadata (title, description, examples)
- `Spectral.TypeInfo` module for runtime type introspection via `__spectra_type_info__/0`
- OpenAPI endpoint documentation support via type annotations
## [0.4.0] - 2026-01-27
### Changed
- Upgraded spectra dependency from 0.3.2 to 0.4.0
- **BREAKING CHANGE**: `Spectral.schema/3` now returns `iodata()` directly instead of `{:ok, iodata()}` tuple, matching the new spectra 0.4.0 API
### Removed
- **BREAKING CHANGE**: Removed `Spectral.schema!/3` function as it's no longer needed (schema/3 now returns directly)
## [0.3.2] - 2026-01-25
### Changed
- Upgraded spectra dependency from 0.3.1 to 0.3.2
- Added Erlang/OTP 27+ requirement to documentation (required by spectra)
- Added documentation section explaining extra fields handling during JSON decoding
## [0.3.1] - 2026-01-25
### Changed
- Upgraded spectra dependency from 0.3.0 to 0.3.1
- Improved type specifications to use `dynamic()` instead of `term()` for runtime-determined types
- Updated project documentation to remove hardcoded dependency version references
## [0.3.0] - 2026-01-20
### Changed
- Upgraded spectra dependency from 0.2.0 to 0.3.0
- JSON Schema generation now uses JSON Schema 2020-12 (previously draft-07)
- OpenAPI specification generation now produces OpenAPI 3.1 (previously 3.0)
- Improved error messages and handling of remote types in enums and parameterized types
- Better documentation of null/optional field handling
## [0.2.0] - 2025-12-15
### Changed
- Extra fields in JSON objects are now silently ignored during decoding, allowing for forward compatibility
## [0.1.4] - 2025-12-13
### Changed
- Both missing fields and explicit `null` values in JSON now decode to `nil` for optional struct fields
## [0.1.3] - 2025-12-13
### Changed
- Support for Elixir 1.18
- Cleanup hex release configuration
- Exclude person example files from release package
## [0.1.2] - 2025-12-12
### Changed
- Make Spectral more idiomatic
- Improve API to be pipe-friendly
- Better error handling
- Update README documentation
## [0.1.1] - 2025-12-10
### Changed
- Better documentation
- Fix hex docs
## [0.1.0] - 2025-11-08
### Added
- Initial release
- Type-driven JSON encoding/decoding
- JSON Schema generation from Elixir type definitions
- OpenAPI 3.0 specification generation
- Wrapper for Erlang spectra library
- Support for nested structs
- Automatic nil value omission in JSON encoding