Packages

Event-driven notification system for Ash Framework with multiple transport types

Retired package: Release invalid - Use vulcora organization package

Current section

Files

Jump to
ash_dispatch lib resource dsl counter.ex
Raw

lib/resource/dsl/counter.ex

defmodule AshDispatch.Resource.Dsl.Counter do
@moduledoc """
Data structure representing a counter definition from the DSL.
This is the target of the `counter` entity in the `counters` section.
## Fields
- `:name` - Unique counter identifier in DSL (atom, e.g., `:pending_orders_counter`)
- `:trigger_on` - List of action names that trigger this counter
- `:counter_name` - Counter name to broadcast (atom)
- `:resource` - Ash resource module to query for counting (optional, defaults to current resource)
- `:query_filter` - Ash.Query filter expression to count items
- `:audience` - Audience type (`:user`, `:admin`, or `:system`)
- `:invalidates` - Frontend query keys to invalidate (list of strings)
- `:user_id_path` - Relationship path to user_id (e.g., `[:cart, :user_id]` for nested relationships)
- `:filter_by_record` - Filter counted resource by triggering record field (e.g., `[field: :cart_id]`)
- `:group` - Counter group for TypeScript generation (e.g., `:orders`, `:tickets`)
- `:global?` - Whether this is a global counter (bypasses policies, no user scoping)
- `:aggregate` - Ash aggregate name to use instead of query_filter
"""
defstruct [
:name,
:trigger_on,
:counter_name,
:resource,
:query_filter,
:audience,
:invalidates,
:user_id_path,
:filter_by_record,
:group,
:aggregate,
global?: false,
__spark_metadata__: nil
]
@type t :: %__MODULE__{
name: atom(),
trigger_on: [atom()],
counter_name: atom(),
resource: module() | nil,
query_filter: any(),
audience: :user | :admin | :system,
invalidates: [String.t()],
user_id_path: [atom()] | nil,
filter_by_record: keyword() | map() | nil,
group: atom() | nil,
global?: boolean(),
aggregate: atom() | nil
}
end