CQRS — separate read and write models.
1// Command side2class OrderCommandHandler {3 constructor(eventStore) {4 this.eventStore = eventStore;5 }67 async createOrder(data) {8 const orderId = generateId();9 await this.eventStore.append(orderId, {10 type: "OrderCreated",11 data: { ...data, orderId },12 });13 return orderId;14 }1516 async addItem(orderId, item) {17 await this.eventStore.append(orderId, {18 type: "ItemAdded",19 data: { orderId, item },20 });21 }22}2324// Query side25class OrderQueryHandler {26 constructor(readModel) {27 this.readModel = readModel;28 }2930 async getOrder(orderId) {31 return this.readModel.getOrder(orderId);32 }3334 async listOrders(userId) {35 return this.readModel.getOrdersByUser(userId);36 }37}3839// Read model (projection)40class OrderReadModel {41 constructor(db) {42 this.db = db;43 }4445 async project(event) {46 switch (event.type) {47 case "OrderCreated":48 await this.db.insert("orders", event.data);49 break;50 case "ItemAdded":51 await this.db.addItem(event.data.orderId, event.data.item);52 break;53 }54 }5556 async getOrder(id) {57 return this.db.query("SELECT * FROM orders WHERE id = $1", [id]);58 }59}