Surfaced by the compliance-library adoption (#393). Small public-API parity gap.
Gap
StoreOptions.Events is an EventStoreOptions facade exposing RegisterTagType<TTag>() / RegisterTagType<TTag>(string) and a pile of flags — but no AddEventType. Marten has opts.Events.AddEventType<TEvent>() and AddEventTypes(IEnumerable<Type>), and the shared JasperFx.Events.IEventRegistry declares void AddEventType(Type).
So a Polecat user following Marten's documented pattern:
opts.Events.AddEventType<StudentEnrolled>(); // does not compile on Polecat
has to go around the facade:
opts.EventGraph.AddEventType(typeof(StudentEnrolled));
which works (StoreOptions.EventGraph is public and EventGraph implements IEventRegistry) but is not discoverable and is not what any Marten-derived docs or samples show.
This is exactly what the compliance fixture had to do — see PolecatComplianceFixture.PolecatComplianceRegistrar.AddEventType in #393, which carries a comment explaining the detour.
Why it matters beyond ergonomics
Pre-registration is not cosmetic. The shared registry doc for AddEventType calls out the async-daemon case: "can help with asynchronous projections where the daemon hasn't yet encountered the event type." A user who cannot reach it from the options facade cannot apply that mitigation without knowing about EventGraph.
Suggested fix
Additive, ~6 lines on EventStoreOptions, mirroring the existing RegisterTagType delegation pattern:
public void AddEventType<TEvent>() => EventGraph!.AddEventType(typeof(TEvent));
public void AddEventType(Type eventType) => EventGraph!.AddEventType(eventType);
public void AddEventTypes(IEnumerable<Type> types) { foreach (var t in types) EventGraph!.AddEventType(t); }
EventGraph is assigned in the StoreOptions constructor, so it is non-null at configure time — same lifetime assumption RegisterTagType already makes with its EventGraph!.
Note: deliberately not returning IEventStoreOptions for fluent chaining. Marten's AddEventType<T>() does, and that return type is precisely what makes marten#5114 (a generic DIM on IEventRegistry) impossible to land there without a source-breaking change. Keeping these void matches the shared interface and leaves the door open.
Related: marten#5114, marten#5119.
🤖 Generated with Claude Code
Surfaced by the compliance-library adoption (#393). Small public-API parity gap.
Gap
StoreOptions.Eventsis anEventStoreOptionsfacade exposingRegisterTagType<TTag>()/RegisterTagType<TTag>(string)and a pile of flags — but noAddEventType. Marten hasopts.Events.AddEventType<TEvent>()andAddEventTypes(IEnumerable<Type>), and the sharedJasperFx.Events.IEventRegistrydeclaresvoid AddEventType(Type).So a Polecat user following Marten's documented pattern:
has to go around the facade:
which works (
StoreOptions.EventGraphis public andEventGraphimplementsIEventRegistry) but is not discoverable and is not what any Marten-derived docs or samples show.This is exactly what the compliance fixture had to do — see
PolecatComplianceFixture.PolecatComplianceRegistrar.AddEventTypein #393, which carries a comment explaining the detour.Why it matters beyond ergonomics
Pre-registration is not cosmetic. The shared registry doc for
AddEventTypecalls out the async-daemon case: "can help with asynchronous projections where the daemon hasn't yet encountered the event type." A user who cannot reach it from the options facade cannot apply that mitigation without knowing aboutEventGraph.Suggested fix
Additive, ~6 lines on
EventStoreOptions, mirroring the existingRegisterTagTypedelegation pattern:EventGraphis assigned in theStoreOptionsconstructor, so it is non-null at configure time — same lifetime assumptionRegisterTagTypealready makes with itsEventGraph!.Note: deliberately not returning
IEventStoreOptionsfor fluent chaining. Marten'sAddEventType<T>()does, and that return type is precisely what makes marten#5114 (a generic DIM onIEventRegistry) impossible to land there without a source-breaking change. Keeping thesevoidmatches the shared interface and leaves the door open.Related: marten#5114, marten#5119.
🤖 Generated with Claude Code