# `Chronicle.Projections.Projection`
[🔗](https://github.com/Cratis/Chronicle.Elixir/blob/main/lib/chronicle/projections/projection.ex#L4)

Macro for defining Chronicle declarative projections.

A declarative projection is a standalone module that defines how events map onto
a read model. Unlike model-bound projections — where `from` declarations live
directly inside the read model module — a declarative projection keeps the read
model as a pure data structure while the projection logic lives in a separate module.

## Quick Example

    defmodule MyApp.Projections.AccountSummaryProjection do
      use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountSummary

      from MyApp.Events.AccountOpened,
        set: [
          account_id: :event_source_id,
          owner_name: :owner_name,
          balance: :initial_balance
        ]

      from MyApp.Events.FundsDeposited,
        add: [balance: :amount]

      from MyApp.Events.FundsWithdrawn,
        subtract: [balance: :amount]
    end

The read model (`AccountSummary`) is a plain struct using `use Chronicle.ReadModels.ReadModel`
with no `from` declarations — it is a pure data shape, not a projection definition.

## Options

  * `:model` — **(required)** the read model module this projection writes into.
  * `:id` — identifier string for this projection. Defaults to the last segment
    of the module name (e.g. `"AccountSummaryProjection"`). A defaulted id (pin it
    explicitly to silence this) emits a one-time warning when discovered — see
    `Chronicle.Discovery.DefaultedIdWarning`.
  * `:passive` — when `true`, the projection does not actively observe events and
    never writes to a materialized sink; its read model is resolved on demand via
    immediate projection when looked up by id. Defaults to `false`.

## Projection Macros

The following macros are available and carry the same options as their counterparts
in `Chronicle.ReadModels.ReadModel`:

- `from/1`, `from/2` — maps properties from an event onto the read model.
- `join/2` — joins a secondary event onto the model by a matching field.
- `removed_with/1`, `removed_with/2` — removes the model instance when the given event occurs.
- `removed_with_join/1`, `removed_with_join/2` — removes the model instance when a secondary
  event matches it by a property instead of by its own key.
- `clear_with/2`, `clear_with/3` — sets a field back to no value; sugar for `from event, clear: [...]`.
- `from_every/1` — applies property mappings on every event, regardless of type.
- `variant_of/2` — declares this projection to be one of several mutually exclusive
  representations of the same logical entity. See `Chronicle.ReadModels.ReadModel`.
- `enters_on/1`, `enters_on/2` — names the event(s) that may create or resurrect this variant.

## Registering with Chronicle.Client

    {Chronicle.Client,
      ...
      projections: [MyApp.Projections.AccountSummaryProjection]}

Or use `otp_app:` auto-discovery — modules that export `__chronicle_projection__/1`
are discovered automatically.

## Introspection

    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:id)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:id_source)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:model)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:from)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:join)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:removed_with)
    MyApp.Projections.AccountSummaryProjection.__chronicle_projection__(:from_every)

# `clear_with`
*macro* 

Sets a field back to no value when the given event occurs. Sugar for `from event, clear: [...]`.

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `enters_on`
*macro* 

Names an event that may create or resurrect this projection's variant. See
`Chronicle.ReadModels.ReadModel.enters_on/2` for full documentation.

# `from`
*macro* 

Declares how an event maps onto the read model.

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `from_every`
*macro* 

Applies property mappings on every event, regardless of type.

Supports dictionary fields keyed by event context values:

    from_every increment: [event_counts: {:event_context, :type}]

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `join`
*macro* 

Declares a join from a secondary event onto the read model.

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `removed_with`
*macro* 

Declares that the read model instance is removed when the given event occurs.

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `removed_with_join`
*macro* 

Declares that the read model instance is removed when a secondary event matches it by a
property, instead of by its own key.

See `Chronicle.ReadModels.ReadModel` for full options documentation.

# `variant_of`
*macro* 

Declares this projection to be one of several mutually exclusive representations of the same
logical entity. See `Chronicle.ReadModels.ReadModel.variant_of/2` for full documentation.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
