All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

[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.