Current section
Files
Jump to
Current section
Files
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.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [0.6.0] - 2026-08-21
### Added
- Built-in data-layer capability sets for `AshClickhouse.DataLayer`,
`AshScylla.DataLayer`, and `AshSqlite.DataLayer` (`AshDyan.DataLayer.Clickhouse`,
`AshDyan.DataLayer.Scylla`, `AshDyan.DataLayer.Sqlite`), alongside the existing
Postgres and ETS support.
- `AshDyan.Charts.to_svg/3` — server-side SVG renderer for `AshDyan.Result`
(`AshDyan.Charts.SVG`). Produces a standalone `<svg>` string with no
JavaScript or external assets, suitable for emails, PDFs, and non-JS
contexts. Supports `:bar`, `:line`, `:pie`, and `:doughnut` chart types with
`:width`, `:height`, and `:title` options; visual conventions match the
Chart.js/ECharts adapters.
- `AshDyan.DataLayer.capabilities/1` and `capabilities_for_data_layer/2` —
normalized metadata describing a data layer's supported analyses, query
primitives (`filter`, `select`, `limit`, `timeout`, `sort`), and aggregation
strategy (`mode`, `functions`). Custom capability modules may implement the
optional `capabilities/1` callback to advertise native features; omitted
sections fall back to conservative defaults.
- `AshDyan.DataLayer.for_data_layer/1` — resolve the capability module for an
explicit data-layer module.
## [0.4.0] - 2026-08-08
### Added
- `AshDyan.Extension` behaviour plus `AshDyan.Extension.Loader` for formal,
composable extensions that register analysis types, data-layer capabilities,
custom aggregates, pipeline hooks, and DSL entities without forking.
- Pipeline hooks via the `AshDyan.Engine.Hook` behaviour: `before_query`,
`after_query`, `before_format`, `after_format` stages, runnable from either
`config :ash_dyan, :hooks` or an extension.
- New optional `AshDyan.Analysis` callbacks with default no-op implementations:
`build_query/2`, `pre_aggregate/2`, `post_aggregate/2`.
- `AshDyan.Engine.format/2` — formats records through the analysis module
(including `pre_aggregate`/`post_aggregate` and presentation post-processing)
and runs pipeline hooks. `Result.format/2` is now deprecated.
- `AshDyan.Analysis.Registry.fetch!/1` — raises on an unknown analysis type.
- New optional `AshDyan.DataLayer` callbacks: `pushdown_aggregate/3`,
`stream/3`, and `paginate/3`.
- Runnable Phoenix + LiveView demo under `examples/ash_dyan_demo/` (in-memory
data layer, seven live charts) with screenshot in `guides/demo_ash_dyan.png`.
### Changed
- `Analysis.Registry`, `DataLayer.for_resource/1`, and aggregate validation now
consult `AshDyan.Extension.Loader.load()` so extension-registered entries are
honored alongside `config :ash_dyan, ...` (config wins on key conflicts).
- `AshDyan.Engine.run_query/3` now runs `after_query` hooks, returns
`{:ok, records}`, and rescues raised errors into `{:error, term}`.
- `AshDyan.DataLayer.Simple.supports?/2` gained a catch-all `false` clause.
## [0.1.0] - 2026-07-10
### Added
- Initial release of AshDyan.
- `dyan` DSL extension for declaring analyzable fields on Ash resources.
- Domain-level `dyan` registry via `AshDyan.Domain`.
- Runtime analysis engine (`AshDyan.run/1,2`) supporting:
- frequency / group-by counts
- numeric aggregates (sum, avg, min, max, count, count_distinct, stddev, variance, median)
- time bucketing
- percentiles
- histograms
- In-memory aggregation bounded by `max_limit`, `max_group_by`, and `query_timeout`.
- Capability check API (`AshDyan.supports?/2`) for data-layer limits.
- Structured errors via `AshDyan.Error` with stable `reason` atoms.
- Chart adapter (`AshDyan.Charts.to_chartjs/1`).
- Documentation guides (`guides/usage.md`, `guides/design.md`).
### Changed
- Removed the shipped Phoenix/Channel/gen_api adapter modules
(`AshDyan.Adapters.*`). AshDyan is now fully standalone — no `plug`
dependency at compile time. Delivery layers are documented as copy-paste
snippets (see README "Building an adapter") rather than versioned APIs.
- `:sum` now rejects `nil` values before reducing (matching every other
aggregate), so a column with a `nil` no longer raises `ArithmeticError`.
- `AshDyan.Engine.apply_filters/2` documents that filters are parsed internally
via `Ash.Filter.parse/2` (not `filter_input`) so the `dyan` whitelist stays
the security boundary.
- `AshDyan.Info.analyzable_field/3` typespec now includes `:histogram`.