Projection With FromEvery
Use an every-event mapping in a declarative projection when a read model property should update whenever any event handled by the projection is processed. This is most useful for audit metadata, event source identifiers, and other fields that should stay synchronized with the latest event.
The exact API name depends on the client. .NET and TypeScript expose FromEvery / fromEvery, while Elixir exposes from_every.
Basic Usage
Section titled “Basic Usage”Map event context metadata when the read model needs to know when it was last touched.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record UserCreatedDeclarativeEvery(string Name, string Email);
[EventType]public record UserEmailChangedDeclarativeEvery(string Email);
public record UserProfileDeclarativeEvery( string Name, string Email, DateTimeOffset LastUpdated);
public class UserProfileDeclarativeEveryProjection : IProjectionFor<UserProfileDeclarativeEvery>{ public void Define(IProjectionBuilderFor<UserProfileDeclarativeEvery> builder) => builder .From<UserCreatedDeclarativeEvery>() .From<UserEmailChangedDeclarativeEvery>() .FromEvery(_ => _ .Set(m => m.LastUpdated) .ToEventContextProperty(c => c.Occurred));}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class UserCreatedDeclarativeEvery(val name: String, val email: String)
@EventTypedata class UserEmailChangedDeclarativeEvery(val email: String)
data class UserProfileDeclarativeEvery( val name: String = "", val email: String = "", val lastUpdated: String = "")
class UserProfileDeclarativeEveryProjection : IProjectionFor<UserProfileDeclarativeEvery> { override fun define(builder: IProjectionBuilderFor<UserProfileDeclarativeEvery>) { builder .from(UserCreatedDeclarativeEvery::class) .from(UserEmailChangedDeclarativeEvery::class) .fromEvery { it.set(UserProfileDeclarativeEvery::lastUpdated).toEventContextProperty("occurred") } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord UserCreatedDeclarativeEvery(String name, String email) {}
@EventTyperecord UserEmailChangedDeclarativeEvery(String email) {}
class UserProfileDeclarativeEvery { public String name = ""; public String email = ""; public String lastUpdated = "";}
class UserProfileDeclarativeEveryProjection implements IProjectionFor<UserProfileDeclarativeEvery> { @Override public void define(IProjectionBuilderFor<UserProfileDeclarativeEvery> builder) { builder .from(UserCreatedDeclarativeEvery.class) .from(UserEmailChangedDeclarativeEvery.class) .fromEvery(feb -> { feb.set("lastUpdated").toEventContextProperty("occurred"); }); }}defmodule MyApp.Events.UserCreatedDeclarativeEvery do use Chronicle.Events.EventType, id: "user-created-declarative-every-v1"
defstruct [:name, :email]end
defmodule MyApp.Events.UserEmailChangedDeclarativeEvery do use Chronicle.Events.EventType, id: "user-email-changed-declarative-every-v1"
defstruct [:email]end
defmodule MyApp.ReadModels.UserProfileDeclarativeEvery do use Chronicle.ReadModels.ReadModel
defstruct [:name, :email, :last_updated]end
defmodule MyApp.Projections.UserProfileDeclarativeEveryProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.UserProfileDeclarativeEvery
alias MyApp.Events.{UserCreatedDeclarativeEvery, UserEmailChangedDeclarativeEvery}
from UserCreatedDeclarativeEvery, set: [ name: :name, email: :email ]
from UserEmailChangedDeclarativeEvery, set: [email: :email]
from_every set: [last_updated: :occurred]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class UserCreatedDeclarativeEvery { constructor(readonly name: string, readonly email: string) {}}
@eventType()class UserEmailChangedDeclarativeEvery { constructor(readonly email: string) {}}
@readModel()class UserProfileDeclarativeEvery { name = ''; email = ''; lastUpdated = new Date();}
@projection('', UserProfileDeclarativeEvery)class UserProfileDeclarativeEveryProjection implements IProjectionFor<UserProfileDeclarativeEvery> { define(builder: IProjectionBuilderFor<UserProfileDeclarativeEvery>): void { builder .from(UserCreatedDeclarativeEvery) .from(UserEmailChangedDeclarativeEvery) .fromEvery(_ => _ .set(m => m.lastUpdated) .toEventContextProperty('occurred')); }}Event Context Fields
Section titled “Event Context Fields”Every-event mappings can map more than one context field.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountTouchedDeclarativeEvery(string Reason);
public record AccountAuditDeclarativeEvery( DateTimeOffset LastUpdated, EventSequenceNumber LastEventSequence, string LastCorrelationId);
public class AccountAuditDeclarativeEveryProjection : IProjectionFor<AccountAuditDeclarativeEvery>{ public void Define(IProjectionBuilderFor<AccountAuditDeclarativeEvery> builder) => builder .From<AccountTouchedDeclarativeEvery>() .FromEvery(_ => _ .Set(m => m.LastUpdated).ToEventContextProperty(c => c.Occurred) .Set(m => m.LastEventSequence).ToEventContextProperty(c => c.SequenceNumber) .Set(m => m.LastCorrelationId).ToEventContextProperty(c => c.CorrelationId));}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class AccountTouchedDeclarativeEvery(val reason: String)
data class AccountAuditDeclarativeEvery( val lastUpdated: String = "", val lastEventSequence: String = "", val lastCorrelationId: String = "")
class AccountAuditDeclarativeEveryProjection : IProjectionFor<AccountAuditDeclarativeEvery> { override fun define(builder: IProjectionBuilderFor<AccountAuditDeclarativeEvery>) { builder .from(AccountTouchedDeclarativeEvery::class) .fromEvery { it.set(AccountAuditDeclarativeEvery::lastUpdated).toEventContextProperty("occurred") it.set(AccountAuditDeclarativeEvery::lastEventSequence).toEventContextProperty("sequenceNumber") it.set(AccountAuditDeclarativeEvery::lastCorrelationId).toEventContextProperty("correlationId") } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord AccountTouchedDeclarativeEvery(String reason) {}
class AccountAuditDeclarativeEvery { public String lastUpdated = ""; public String lastEventSequence = ""; public String lastCorrelationId = "";}
class AccountAuditDeclarativeEveryProjection implements IProjectionFor<AccountAuditDeclarativeEvery> { @Override public void define(IProjectionBuilderFor<AccountAuditDeclarativeEvery> builder) { builder .from(AccountTouchedDeclarativeEvery.class) .fromEvery(feb -> { feb.set("lastUpdated").toEventContextProperty("occurred"); feb.set("lastEventSequence").toEventContextProperty("sequenceNumber"); feb.set("lastCorrelationId").toEventContextProperty("correlationId"); }); }}defmodule MyApp.Events.AccountTouchedDeclarativeEvery do use Chronicle.Events.EventType, id: "account-touched-declarative-every-v1"
defstruct [:reason]end
defmodule MyApp.ReadModels.AccountAuditDeclarativeEvery do use Chronicle.ReadModels.ReadModel
defstruct [:last_updated, :last_event_sequence, :last_correlation_id]end
defmodule MyApp.Projections.AccountAuditDeclarativeEveryProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountAuditDeclarativeEvery
alias MyApp.Events.AccountTouchedDeclarativeEvery
from AccountTouchedDeclarativeEvery
from_every set: [ last_updated: :occurred, last_event_sequence: "$context.sequenceNumber", last_correlation_id: "$context.correlationId" ]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class AccountTouchedDeclarativeEvery { constructor(readonly reason: string) {}}
@readModel()class AccountAuditDeclarativeEvery { lastUpdated = new Date(); lastEventSequence = 0n; lastCorrelationId = '';}
@projection('', AccountAuditDeclarativeEvery)class AccountAuditDeclarativeEveryProjection implements IProjectionFor<AccountAuditDeclarativeEvery> { define(builder: IProjectionBuilderFor<AccountAuditDeclarativeEvery>): void { builder .from(AccountTouchedDeclarativeEvery) .fromEvery(_ => _ .set(m => m.lastUpdated).toEventContextProperty('occurred') .set(m => m.lastEventSequence).toEventContextProperty('sequenceNumber') .set(m => m.lastCorrelationId).toEventContextProperty('correlationId')); }}Event Source Id
Section titled “Event Source Id”Map the event source id when the read model’s primary identifier is not otherwise populated from each event payload.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountOpenedDeclarativeEvery(string OwnerName);
public record AccountSummaryDeclarativeEvery( string AccountId, string OwnerName);
public class AccountSummaryDeclarativeEveryProjection : IProjectionFor<AccountSummaryDeclarativeEvery>{ public void Define(IProjectionBuilderFor<AccountSummaryDeclarativeEvery> builder) => builder .From<AccountOpenedDeclarativeEvery>() .FromEvery(_ => _ .Set(m => m.AccountId) .ToEventSourceId());}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class AccountOpenedDeclarativeEvery(val ownerName: String)
data class AccountSummaryDeclarativeEvery( val accountId: String = "", val ownerName: String = "")
class AccountSummaryDeclarativeEveryProjection : IProjectionFor<AccountSummaryDeclarativeEvery> { override fun define(builder: IProjectionBuilderFor<AccountSummaryDeclarativeEvery>) { builder .from(AccountOpenedDeclarativeEvery::class) .fromEvery { it.set(AccountSummaryDeclarativeEvery::accountId).toEventSourceId() } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord AccountOpenedDeclarativeEvery(String ownerName) {}
class AccountSummaryDeclarativeEvery { public String accountId = ""; public String ownerName = "";}
class AccountSummaryDeclarativeEveryProjection implements IProjectionFor<AccountSummaryDeclarativeEvery> { @Override public void define(IProjectionBuilderFor<AccountSummaryDeclarativeEvery> builder) { builder .from(AccountOpenedDeclarativeEvery.class) .fromEvery(feb -> { feb.set("accountId").toEventSourceId(); }); }}defmodule MyApp.Events.AccountOpenedDeclarativeEvery do use Chronicle.Events.EventType, id: "account-opened-declarative-every-v1"
defstruct [:owner_name]end
defmodule MyApp.ReadModels.AccountSummaryDeclarativeEvery do use Chronicle.ReadModels.ReadModel
defstruct [:account_id, :owner_name]end
defmodule MyApp.Projections.AccountSummaryDeclarativeEveryProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountSummaryDeclarativeEvery
alias MyApp.Events.AccountOpenedDeclarativeEvery
from AccountOpenedDeclarativeEvery, set: [owner_name: :owner_name]
from_every set: [account_id: :event_source_id]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class AccountOpenedDeclarativeEvery { constructor(readonly ownerName: string) {}}
@readModel()class AccountSummaryDeclarativeEvery { accountId = ''; ownerName = '';}
@projection('', AccountSummaryDeclarativeEvery)class AccountSummaryDeclarativeEveryProjection implements IProjectionFor<AccountSummaryDeclarativeEvery> { define(builder: IProjectionBuilderFor<AccountSummaryDeclarativeEvery>): void { builder .from(AccountOpenedDeclarativeEvery) .fromEvery(_ => _ .set(m => m.accountId) .toEventSourceId()); }}Child Projection Inclusion
Section titled “Child Projection Inclusion”Some clients let the projection decide whether child projection events should update parent-level every-event fields.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record OrderCreatedDeclarativeEveryExclude(string OrderNumber);
public record OrderAuditDeclarativeEveryExclude( string OrderNumber, DateTimeOffset LastUpdated);
public class OrderAuditDeclarativeEveryExcludeProjection : IProjectionFor<OrderAuditDeclarativeEveryExclude>{ public void Define(IProjectionBuilderFor<OrderAuditDeclarativeEveryExclude> builder) => builder .From<OrderCreatedDeclarativeEveryExclude>() .FromEvery(_ => _ .Set(m => m.LastUpdated) .ToEventContextProperty(c => c.Occurred) .ExcludeChildProjections());}Kotlin does not support this workflow yet.Java does not support this workflow yet.defmodule MyApp.Events.OrderCreatedDeclarativeEveryExclude do use Chronicle.Events.EventType, id: "order-created-declarative-every-exclude-v1"
defstruct [:order_number]end
defmodule MyApp.ReadModels.OrderAuditDeclarativeEveryExclude do use Chronicle.ReadModels.ReadModel
defstruct [:order_number, :last_updated]end
defmodule MyApp.Projections.OrderAuditDeclarativeEveryExcludeProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.OrderAuditDeclarativeEveryExclude
alias MyApp.Events.OrderCreatedDeclarativeEveryExclude
from OrderCreatedDeclarativeEveryExclude
from_every set: [last_updated: :occurred], include_children: falseendimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class OrderCreatedDeclarativeEveryExclude { constructor(readonly orderNumber: string) {}}
@readModel()class OrderAuditDeclarativeEveryExclude { orderNumber = ''; lastUpdated = new Date();}
@projection('', OrderAuditDeclarativeEveryExclude)class OrderAuditDeclarativeEveryExcludeProjection implements IProjectionFor<OrderAuditDeclarativeEveryExclude> { define(builder: IProjectionBuilderFor<OrderAuditDeclarativeEveryExclude>): void { builder .from(OrderCreatedDeclarativeEveryExclude) .fromEvery(_ => _ .set(m => m.lastUpdated) .toEventContextProperty('occurred') .excludeChildProjections()); }}When child projections are included, parent metadata can update for events that only affect a child item.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record OrderCreatedDeclarativeEveryChildren(string OrderNumber);
[EventType]public record ItemAddedDeclarativeEveryChildren(string OrderId, string ProductId, string ProductName, int Quantity);
[EventType]public record ItemQuantityChangedDeclarativeEveryChildren(string OrderId, string ProductId, int Quantity);
public record OrderDeclarativeEveryChildren( string OrderNumber, DateTimeOffset LastModified, IEnumerable<OrderItemDeclarativeEveryChildren> Items);
public record OrderItemDeclarativeEveryChildren( string ProductId, string ProductName, int Quantity);
public class OrderDeclarativeEveryChildrenProjection : IProjectionFor<OrderDeclarativeEveryChildren>{ public void Define(IProjectionBuilderFor<OrderDeclarativeEveryChildren> builder) => builder .From<OrderCreatedDeclarativeEveryChildren>() .FromEvery(_ => _ .Set(m => m.LastModified) .ToEventContextProperty(c => c.Occurred)) .Children(m => m.Items, children => children .IdentifiedBy(m => m.ProductId) .From<ItemAddedDeclarativeEveryChildren>(_ => _ .UsingKey(e => e.ProductId) .UsingParentKey(e => e.OrderId)) .From<ItemQuantityChangedDeclarativeEveryChildren>(_ => _ .UsingKey(e => e.ProductId) .UsingParentKey(e => e.OrderId)));}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionForimport java.time.Instant
@EventTypedata class OrderCreatedDeclarativeEveryChildren(val orderNumber: String)
@EventTypedata class ItemAddedDeclarativeEveryChildren( val orderId: String, val productId: String, val productName: String, val quantity: Int)
@EventTypedata class ItemQuantityChangedDeclarativeEveryChildren( val orderId: String, val productId: String, val quantity: Int)
data class OrderDeclarativeEveryChildren( val orderNumber: String = "", val lastModified: Instant = Instant.EPOCH, val items: List<OrderItemDeclarativeEveryChildren> = emptyList())
data class OrderItemDeclarativeEveryChildren( val productId: String = "", val productName: String = "", val quantity: Int = 0)
class OrderDeclarativeEveryChildrenProjection : IProjectionFor<OrderDeclarativeEveryChildren> { override fun define(builder: IProjectionBuilderFor<OrderDeclarativeEveryChildren>) { builder .from(OrderCreatedDeclarativeEveryChildren::class) .fromEvery { it.set(OrderDeclarativeEveryChildren::lastModified).toEventContextProperty("occurred") } .children(OrderDeclarativeEveryChildren::items, OrderItemDeclarativeEveryChildren::class) { children -> children .identifiedBy("productId") .from(ItemAddedDeclarativeEveryChildren::class) { it.usingKey("productId").usingParentKey("orderId") } .from(ItemQuantityChangedDeclarativeEveryChildren::class) { it.usingKey("productId").usingParentKey("orderId") } } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
import java.time.Instant;import java.util.List;
@EventTyperecord OrderCreatedDeclarativeEveryChildren(String orderNumber) {}
@EventTyperecord ItemAddedDeclarativeEveryChildren(String orderId, String productId, String productName, int quantity) {}
@EventTyperecord ItemQuantityChangedDeclarativeEveryChildren(String orderId, String productId, int quantity) {}
class OrderDeclarativeEveryChildren { public String orderNumber = ""; public Instant lastModified = Instant.EPOCH; public List<OrderItemDeclarativeEveryChildren> items = List.of();}
record OrderItemDeclarativeEveryChildren(String productId, String productName, int quantity) {}
class OrderDeclarativeEveryChildrenProjection implements IProjectionFor<OrderDeclarativeEveryChildren> { @Override public void define(IProjectionBuilderFor<OrderDeclarativeEveryChildren> builder) { builder .from(OrderCreatedDeclarativeEveryChildren.class) .fromEvery(feb -> { feb.set("lastModified").toEventContextProperty("occurred"); }) .children("items", OrderItemDeclarativeEveryChildren.class, children -> { children .identifiedBy("productId") .from(ItemAddedDeclarativeEveryChildren.class, fb -> { fb.usingKey("productId"); fb.usingParentKey("orderId"); }) .from(ItemQuantityChangedDeclarativeEveryChildren.class, fb -> { fb.usingKey("productId"); fb.usingParentKey("orderId"); }); }); }}Elixir does not support this workflow yet.import { eventType, IProjectionBuilderFor, IProjectionFor, projection } from '@cratis/chronicle';
@eventType()class OrderCreatedDeclarativeEveryChildren { constructor(readonly orderNumber: string) {}}
@eventType()class ItemAddedDeclarativeEveryChildren { constructor( readonly orderId: string, readonly productId: string, readonly productName: string, readonly quantity: number ) {}}
@eventType()class ItemQuantityChangedDeclarativeEveryChildren { constructor(readonly orderId: string, readonly productId: string, readonly quantity: number) {}}
class OrderItemDeclarativeEveryChildren { productId = ''; productName = ''; quantity = 0;}
class OrderDeclarativeEveryChildren { orderNumber = ''; lastModified = new Date(); items: OrderItemDeclarativeEveryChildren[] = [];}
@projection()class OrderDeclarativeEveryChildrenProjection implements IProjectionFor<OrderDeclarativeEveryChildren> { define(builder: IProjectionBuilderFor<OrderDeclarativeEveryChildren>): void { builder .from(OrderCreatedDeclarativeEveryChildren) .fromEvery(_ => _ .set(m => m.lastModified) .toEventContextProperty('occurred')) .children<OrderItemDeclarativeEveryChildren>(m => m.items, children => children .identifiedBy(m => m.productId) .from(ItemAddedDeclarativeEveryChildren, _ => _ .usingKey(e => e.productId) .usingParentKey(e => e.orderId)) .from(ItemQuantityChangedDeclarativeEveryChildren, _ => _ .usingKey(e => e.productId) .usingParentKey(e => e.orderId))); }}Multiple Declarations
Section titled “Multiple Declarations”Clients that support multiple every-event declarations merge the property mappings into one projection definition.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record UserChangedDeclarativeEveryMultiple(string Name);
public record UserAuditDeclarativeEveryMultiple( string Name, DateTimeOffset LastUpdated, string ModifiedBy);
public class UserAuditDeclarativeEveryMultipleProjection : IProjectionFor<UserAuditDeclarativeEveryMultiple>{ public void Define(IProjectionBuilderFor<UserAuditDeclarativeEveryMultiple> builder) => builder .From<UserChangedDeclarativeEveryMultiple>() .FromEvery(_ => _ .Set(m => m.LastUpdated) .ToEventContextProperty(c => c.Occurred)) .FromEvery(_ => _ .Set(m => m.ModifiedBy) .ToEventContextProperty(c => c.CausedBy));}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class UserChangedDeclarativeEveryMultiple(val name: String)
data class UserAuditDeclarativeEveryMultiple( val name: String = "", val lastUpdated: String = "", val modifiedBy: String = "")
class UserAuditDeclarativeEveryMultipleProjection : IProjectionFor<UserAuditDeclarativeEveryMultiple> { override fun define(builder: IProjectionBuilderFor<UserAuditDeclarativeEveryMultiple>) { builder .from(UserChangedDeclarativeEveryMultiple::class) .fromEvery { it.set(UserAuditDeclarativeEveryMultiple::lastUpdated).toEventContextProperty("occurred") } .fromEvery { it.set(UserAuditDeclarativeEveryMultiple::modifiedBy).toEventContextProperty("causedBy") } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord UserChangedDeclarativeEveryMultiple(String name) {}
class UserAuditDeclarativeEveryMultiple { public String name = ""; public String lastUpdated = ""; public String modifiedBy = "";}
class UserAuditDeclarativeEveryMultipleProjection implements IProjectionFor<UserAuditDeclarativeEveryMultiple> { @Override public void define(IProjectionBuilderFor<UserAuditDeclarativeEveryMultiple> builder) { builder .from(UserChangedDeclarativeEveryMultiple.class) .fromEvery(feb -> { feb.set("lastUpdated").toEventContextProperty("occurred"); }) .fromEvery(feb -> { feb.set("modifiedBy").toEventContextProperty("causedBy"); }); }}defmodule MyApp.Events.UserChangedEveryMultiple do use Chronicle.Events.EventType, id: "user-changed-every-multiple"
defstruct [:name]end
defmodule MyApp.ReadModels.UserAuditEveryMultiple do use Chronicle.ReadModels.ReadModel
defstruct id: nil, name: nil, last_updated: nil, subject_id: nil
from MyApp.Events.UserChangedEveryMultiple, set: [name: :name]
# Every declaration contributes - they are merged, not replaced. from_every(set: [last_updated: :occurred]) from_every(set: [subject_id: :event_source_id])endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class UserChangedDeclarativeEveryMultiple { constructor(readonly name: string) {}}
@readModel()class UserAuditDeclarativeEveryMultiple { name = ''; lastUpdated = new Date(); modifiedBy = '';}
@projection('', UserAuditDeclarativeEveryMultiple)class UserAuditDeclarativeEveryMultipleProjection implements IProjectionFor<UserAuditDeclarativeEveryMultiple> { define(builder: IProjectionBuilderFor<UserAuditDeclarativeEveryMultiple>): void { builder .from(UserChangedDeclarativeEveryMultiple) .fromEvery(_ => _ .set(m => m.lastUpdated) .toEventContextProperty('occurred')) .fromEvery(_ => _ .set(m => m.modifiedBy) .toEventContextProperty('causedBy')); }}Common Use Cases
Section titled “Common Use Cases”| Use case | Typical source |
|---|---|
| Audit timestamp | Event context occurrence time |
| Event sequencing | Event context sequence number |
| Correlation tracking | Event context correlation id |
| Event source identification | Event source id |
Use event-specific mappings when the property should update only for selected event types.