Projection
A read-side view folded from events. CQRS: writes go through actors, reads through projections.
Projections are pure folds: (state, event) => state. No side effects, no reads from external systems. The runtime replays event history into them.
Shape
ts
import { defineProjection } from "@nwire/forge";
export const SubmissionsByStudent = defineProjection<{
byStudent: Record<string, SubmissionSummary[]>;
}>("submissions-by-student", {
description: "Index of submissions keyed by studentId — feeds Avi's history view.",
freshness: { p95MsBehindStream: 50 }, // Studio scores observed lag against this
listens: [
AnswerSubmittedEvent,
SubmissionAutoGradedEvent,
SubmissionFlaggedForReviewEvent,
SubmissionManuallyGradedEvent,
],
initial: () => ({ byStudent: {} }),
on: {
[AnswerSubmittedEvent.name]: (state, event) => ({
byStudent: {
...state.byStudent,
[event.studentId]: [
...(state.byStudent[event.studentId] ?? []),
{ id: event.submissionId, status: "submitted", submittedAt: event.submittedAt },
],
},
}),
[SubmissionAutoGradedEvent.name]: (state, event) => updateOne(state, event.studentId, event.submissionId, (s) => ({
...s,
status: "graded",
verdict: event.verdict,
})),
// …
},
});Where do they live?
In memory by default (InMemoryProjectionStore). For persistence:
ts
import { MongoProjectionStore } from "@nwire/store-mongo";
import { FileProjectionStore } from "@nwire/store-file";
createApp({ modules, projectionStore: new MongoProjectionStore(client) });Multi-tenancy
Projection state is partitioned by envelope.tenant. Each tenant gets its own folded state. No code change required — the framework partitions automatically.
Backfill / replay
Projections are pure functions over the event log. Replay a tenant's state by re-feeding events into runtime.publish after clearing the store. (Studio's "Replay" feature, coming.)
Studio-aware metadata
| Field | What Studio does |
|---|---|
description | Tooltip / detail panel |
freshness: { p95MsBehindStream } | Compares declared lag target to observed lag from telemetry |
See also
- defineProjection
- Query — read functions over projections
- Event — what gets folded