Projection With FromAll
FromAll is a .NET declarative projection API that maps properties from every event considered by the projection, excluding child projection events by default. Other clients expose the same underlying concept through their every-event APIs configured to exclude children; see Projection With FromEvery for the full every-event feature set.
Use FromAll in .NET when the projection should express that a mapping belongs to the all-events portion of the projection definition. In Elixir, the same default (excluding child projection events) is what from_every does when :include_children is omitted. In TypeScript, call excludeChildProjections() on the fromEvery builder to get the same behavior.
Basic Usage
Section titled “Basic Usage”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record UserCreatedDeclarativeAll(string Name, string Email);
[EventType]public record UserEmailChangedDeclarativeAll(string Email);
public record UserProfileDeclarativeAll( string Name, string Email, DateTimeOffset LastUpdated);
public class UserProfileDeclarativeAllProjection : IProjectionFor<UserProfileDeclarativeAll>{ public void Define(IProjectionBuilderFor<UserProfileDeclarativeAll> builder) => builder .From<UserCreatedDeclarativeAll>() .From<UserEmailChangedDeclarativeAll>() .FromAll(_ => _ .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 UserCreatedDeclarativeAll(val name: String, val email: String)
@EventTypedata class UserEmailChangedDeclarativeAll(val email: String)
data class UserProfileDeclarativeAll( val name: String = "", val email: String = "", val lastUpdated: String = "")
class UserProfileDeclarativeAllProjection : IProjectionFor<UserProfileDeclarativeAll> { override fun define(builder: IProjectionBuilderFor<UserProfileDeclarativeAll>) { builder .from(UserCreatedDeclarativeAll::class) .from(UserEmailChangedDeclarativeAll::class) .fromAll { it.set(UserProfileDeclarativeAll::lastUpdated).toEventContextProperty("occurred") } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord UserCreatedDeclarativeAll(String name, String email) {}
@EventTyperecord UserEmailChangedDeclarativeAll(String email) {}
class UserProfileDeclarativeAll { public String name = ""; public String email = ""; public String lastUpdated = "";}
class UserProfileDeclarativeAllProjection implements IProjectionFor<UserProfileDeclarativeAll> { @Override public void define(IProjectionBuilderFor<UserProfileDeclarativeAll> builder) { builder .from(UserCreatedDeclarativeAll.class) .from(UserEmailChangedDeclarativeAll.class) .fromAll(feb -> { feb.set("lastUpdated").toEventContextProperty("occurred"); }); }}defmodule MyApp.Events.UserCreatedDeclarativeAll do use Chronicle.Events.EventType, id: "user-created-declarative-all-v1"
defstruct [:name, :email]end
defmodule MyApp.Events.UserEmailChangedDeclarativeAll do use Chronicle.Events.EventType, id: "user-email-changed-declarative-all-v1"
defstruct [:email]end
defmodule MyApp.ReadModels.UserProfileDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:name, :email, :last_updated]end
defmodule MyApp.Projections.UserProfileDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.UserProfileDeclarativeAll
alias MyApp.Events.{UserCreatedDeclarativeAll, UserEmailChangedDeclarativeAll}
from UserCreatedDeclarativeAll from UserEmailChangedDeclarativeAll
from_every set: [last_updated: :occurred]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class UserCreatedDeclarativeAll { constructor(readonly name: string, readonly email: string) {}}
@eventType()class UserEmailChangedDeclarativeAll { constructor(readonly email: string) {}}
@readModel()class UserProfileDeclarativeAll { name = ''; email = ''; lastUpdated = new Date();}
@projection('', UserProfileDeclarativeAll)class UserProfileDeclarativeAllProjection implements IProjectionFor<UserProfileDeclarativeAll> { define(builder: IProjectionBuilderFor<UserProfileDeclarativeAll>): void { builder .from(UserCreatedDeclarativeAll) .from(UserEmailChangedDeclarativeAll) .fromEvery(_ => _ .set(m => m.lastUpdated) .toEventContextProperty('occurred') .excludeChildProjections()); }}Event Context Fields
Section titled “Event Context Fields”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountTouchedDeclarativeAll(string Reason);
public record AccountAuditDeclarativeAll( DateTimeOffset LastUpdated, EventSequenceNumber LastEventSequence, string LastCorrelationId);
public class AccountAuditDeclarativeAllProjection : IProjectionFor<AccountAuditDeclarativeAll>{ public void Define(IProjectionBuilderFor<AccountAuditDeclarativeAll> builder) => builder .From<AccountTouchedDeclarativeAll>() .FromAll(_ => _ .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 AccountTouchedDeclarativeAll(val reason: String)
data class AccountAuditDeclarativeAll( val lastUpdated: String = "", val lastEventSequence: String = "", val lastCorrelationId: String = "")
class AccountAuditDeclarativeAllProjection : IProjectionFor<AccountAuditDeclarativeAll> { override fun define(builder: IProjectionBuilderFor<AccountAuditDeclarativeAll>) { builder .from(AccountTouchedDeclarativeAll::class) .fromAll { it.set(AccountAuditDeclarativeAll::lastUpdated).toEventContextProperty("occurred") it.set(AccountAuditDeclarativeAll::lastEventSequence).toEventContextProperty("sequenceNumber") it.set(AccountAuditDeclarativeAll::lastCorrelationId).toEventContextProperty("correlationId") } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord AccountTouchedDeclarativeAll(String reason) {}
class AccountAuditDeclarativeAll { public String lastUpdated = ""; public String lastEventSequence = ""; public String lastCorrelationId = "";}
class AccountAuditDeclarativeAllProjection implements IProjectionFor<AccountAuditDeclarativeAll> { @Override public void define(IProjectionBuilderFor<AccountAuditDeclarativeAll> builder) { builder .from(AccountTouchedDeclarativeAll.class) .fromAll(feb -> { feb.set("lastUpdated").toEventContextProperty("occurred"); feb.set("lastEventSequence").toEventContextProperty("sequenceNumber"); feb.set("lastCorrelationId").toEventContextProperty("correlationId"); }); }}defmodule MyApp.Events.AccountTouchedDeclarativeAll do use Chronicle.Events.EventType, id: "account-touched-declarative-all-v1"
defstruct [:reason]end
defmodule MyApp.ReadModels.AccountAuditDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:last_updated, :last_event_sequence, :last_correlation_id]end
defmodule MyApp.Projections.AccountAuditDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountAuditDeclarativeAll
alias MyApp.Events.AccountTouchedDeclarativeAll
from AccountTouchedDeclarativeAll
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 AccountTouchedDeclarativeAll { constructor(readonly reason: string) {}}
@readModel()class AccountAuditDeclarativeAll { lastUpdated = new Date(); lastEventSequence = 0n; lastCorrelationId = '';}
@projection('', AccountAuditDeclarativeAll)class AccountAuditDeclarativeAllProjection implements IProjectionFor<AccountAuditDeclarativeAll> { define(builder: IProjectionBuilderFor<AccountAuditDeclarativeAll>): void { builder .from(AccountTouchedDeclarativeAll) .fromEvery(_ => _ .set(m => m.lastUpdated).toEventContextProperty('occurred') .set(m => m.lastEventSequence).toEventContextProperty('sequenceNumber') .set(m => m.lastCorrelationId).toEventContextProperty('correlationId') .excludeChildProjections()); }}Event Source Id
Section titled “Event Source Id”using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record AccountOpenedDeclarativeAll(string OwnerName);
public record AccountSummaryDeclarativeAll( string AccountId, string OwnerName);
public class AccountSummaryDeclarativeAllProjection : IProjectionFor<AccountSummaryDeclarativeAll>{ public void Define(IProjectionBuilderFor<AccountSummaryDeclarativeAll> builder) => builder .From<AccountOpenedDeclarativeAll>() .FromAll(_ => _ .Set(m => m.AccountId) .ToEventSourceId());}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class AccountOpenedDeclarativeAll(val ownerName: String)
data class AccountSummaryDeclarativeAll( val accountId: String = "", val ownerName: String = "")
class AccountSummaryDeclarativeAllProjection : IProjectionFor<AccountSummaryDeclarativeAll> { override fun define(builder: IProjectionBuilderFor<AccountSummaryDeclarativeAll>) { builder .from(AccountOpenedDeclarativeAll::class) .fromAll { it.set(AccountSummaryDeclarativeAll::accountId).toEventSourceId() } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord AccountOpenedDeclarativeAll(String ownerName) {}
class AccountSummaryDeclarativeAll { public String accountId = ""; public String ownerName = "";}
class AccountSummaryDeclarativeAllProjection implements IProjectionFor<AccountSummaryDeclarativeAll> { @Override public void define(IProjectionBuilderFor<AccountSummaryDeclarativeAll> builder) { builder .from(AccountOpenedDeclarativeAll.class) .fromAll(feb -> { feb.set("accountId").toEventSourceId(); }); }}defmodule MyApp.Events.AccountOpenedDeclarativeAll do use Chronicle.Events.EventType, id: "account-opened-declarative-all-v1"
defstruct [:owner_name]end
defmodule MyApp.ReadModels.AccountSummaryDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:account_id, :owner_name]end
defmodule MyApp.Projections.AccountSummaryDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.AccountSummaryDeclarativeAll
alias MyApp.Events.AccountOpenedDeclarativeAll
from AccountOpenedDeclarativeAll
from_every set: [account_id: :event_source_id]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class AccountOpenedDeclarativeAll { constructor(readonly ownerName: string) {}}
@readModel()class AccountSummaryDeclarativeAll { accountId = ''; ownerName = '';}
@projection('', AccountSummaryDeclarativeAll)class AccountSummaryDeclarativeAllProjection implements IProjectionFor<AccountSummaryDeclarativeAll> { define(builder: IProjectionBuilderFor<AccountSummaryDeclarativeAll>): void { builder .from(AccountOpenedDeclarativeAll) .fromEvery(_ => _ .set(m => m.accountId) .toEventSourceId() .excludeChildProjections()); }}With Event-Specific Mappings
Section titled “With Event-Specific Mappings”FromAll can sit beside event-specific From mappings. Use event-specific mappings for business state, and reserve FromAll for metadata that should update for every projected event.
using Cratis.Chronicle.Events;using Cratis.Chronicle.Projections;
[EventType]public record OrderCreatedDeclarativeAll(string OrderNumber);
[EventType]public record OrderShippedDeclarativeAll(string TrackingNumber);
public record OrderDeclarativeAll( string OrderNumber, string Status, DateTimeOffset LastModified);
public class OrderDeclarativeAllProjection : IProjectionFor<OrderDeclarativeAll>{ public void Define(IProjectionBuilderFor<OrderDeclarativeAll> builder) => builder .FromAll(_ => _ .Set(m => m.LastModified) .ToEventContextProperty(c => c.Occurred)) .From<OrderCreatedDeclarativeAll>(_ => _ .Set(m => m.Status) .ToValue("Placed")) .From<OrderShippedDeclarativeAll>(_ => _ .Set(m => m.Status) .ToValue("Shipped"));}import io.cratis.chronicle.events.EventTypeimport io.cratis.chronicle.projections.IProjectionBuilderForimport io.cratis.chronicle.projections.IProjectionFor
@EventTypedata class OrderCreatedDeclarativeAll(val orderNumber: String)
@EventTypedata class OrderShippedDeclarativeAll(val trackingNumber: String)
data class OrderDeclarativeAll( val orderNumber: String = "", val status: String = "", val lastModified: String = "")
class OrderDeclarativeAllProjection : IProjectionFor<OrderDeclarativeAll> { override fun define(builder: IProjectionBuilderFor<OrderDeclarativeAll>) { builder .fromAll { it.set(OrderDeclarativeAll::lastModified).toEventContextProperty("occurred") } .from(OrderCreatedDeclarativeAll::class) { it.set(OrderDeclarativeAll::status).to { "Placed" } } .from(OrderShippedDeclarativeAll::class) { it.set(OrderDeclarativeAll::status).to { "Shipped" } } }}import io.cratis.chronicle.events.EventType;import io.cratis.chronicle.projections.IProjectionBuilderFor;import io.cratis.chronicle.projections.IProjectionFor;
@EventTyperecord OrderCreatedDeclarativeAll(String orderNumber) {}
@EventTyperecord OrderShippedDeclarativeAll(String trackingNumber) {}
class OrderDeclarativeAll { public String orderNumber = ""; public String status = ""; public String lastModified = "";}
class OrderDeclarativeAllProjection implements IProjectionFor<OrderDeclarativeAll> { @Override public void define(IProjectionBuilderFor<OrderDeclarativeAll> builder) { builder .fromAll(feb -> { feb.set("lastModified").toEventContextProperty("occurred"); }) .from(OrderCreatedDeclarativeAll.class, fb -> { fb.<String>set("status").to(e -> "Placed"); }) .from(OrderShippedDeclarativeAll.class, fb -> { fb.<String>set("status").to(e -> "Shipped"); }); }}defmodule MyApp.Events.OrderCreatedDeclarativeAll do use Chronicle.Events.EventType, id: "order-created-declarative-all"
defstruct [:order_number]end
defmodule MyApp.Events.OrderShippedDeclarativeAll do use Chronicle.Events.EventType, id: "order-shipped-declarative-all"
defstruct [:tracking_number]end
defmodule MyApp.ReadModels.OrderDeclarativeAll do use Chronicle.ReadModels.ReadModel
defstruct [:order_number, :status, :last_modified]end
defmodule MyApp.Projections.OrderDeclarativeAllProjection do use Chronicle.Projections.Projection, model: MyApp.ReadModels.OrderDeclarativeAll
alias MyApp.Events.{OrderCreatedDeclarativeAll, OrderShippedDeclarativeAll}
# Elixir's from_every excludes child-projection events by default — the # same default FromAll uses in .NET. from_every set: [last_modified: :occurred]
from OrderCreatedDeclarativeAll, set: [ order_number: :order_number, status: "$value(Placed)" ]
from OrderShippedDeclarativeAll, set: [status: "$value(Shipped)"]endimport { eventType, IProjectionBuilderFor, IProjectionFor, projection, readModel } from '@cratis/chronicle';
@eventType()class OrderCreatedDeclarativeAll { constructor(readonly orderNumber: string) {}}
@eventType()class OrderShippedDeclarativeAll { constructor(readonly trackingNumber: string) {}}
@readModel()class OrderDeclarativeAll { orderNumber = ''; status = ''; lastModified = new Date();}
@projection('', OrderDeclarativeAll)class OrderDeclarativeAllProjection implements IProjectionFor<OrderDeclarativeAll> { define(builder: IProjectionBuilderFor<OrderDeclarativeAll>): void { builder .fromEvery(_ => _ .set(m => m.lastModified) .toEventContextProperty('occurred') .excludeChildProjections()) .from(OrderCreatedDeclarativeAll, _ => _ .set(m => m.status) .toValue('Placed')) .from(OrderShippedDeclarativeAll, _ => _ .set(m => m.status) .toValue('Shipped')); }}FromAll And FromEvery
Section titled “FromAll And FromEvery”| API | Use it when |
|---|---|
FromAll | You are using the .NET declarative projection API and want to express an all-events mapping. |
FromEvery | You want the portable every-event concept, or you are using a client that exposes the concept under that name. |
Prefer event context sources for audit fields because every event has the same context shape. Use event payload properties only when the event contracts intentionally share the same property.