Event sourcing — store state as sequence of events.
1class EventStore {2 constructor() {3 this.events = [];4 this.projections = new Map();5 }67 append(aggregateId, event) {8 const entry = {9 id: this.events.length,10 aggregateId,11 type: event.type,12 data: event.data,13 timestamp: Date.now(),14 };15 this.events.push(entry);16 this.project(entry);17 }1819 getEvents(aggregateId) {20 return this.events.filter(e => e.aggregateId === aggregateId);21 }2223 project(event) {24 this.projections.forEach(projection => projection(event));25 }2627 addProjection(name, handler) {28 this.projections.set(name, handler);29 }30}3132// Usage33const store = new EventStore();3435// Add projection36store.addProjection("orderSummary", (event) => {37 if (event.type === "OrderCreated") {38 console.log(`Order ${event.data.id} created`);39 }40});4142// Append events43store.append("order-123", {44 type: "OrderCreated",45 data: { id: "order-123", items: ["item1"] },46});4748store.append("order-123", {49 type: "OrderPaid",50 data: { amount: 99.99 },51});5253// Rebuild state54function rebuildState(aggregateId) {55 return store.getEvents(aggregateId).reduce((state, event) => {56 switch (event.type) {57 case "OrderCreated": return { ...state, ...event.data, status: "created" };58 case "OrderPaid": return { ...state, status: "paid", amount: event.data.amount };59 default: return state;60 }61 }, {});62}