@zeeshan60/event-processor
v1.0.152
Published
Shared event sourcing infrastructure for Loan Tracker projects
Maintainers
Readme
Event Processor
Shared event sourcing infrastructure for Loan Tracker projects.
Overview
This package provides the core building blocks for implementing event sourcing patterns across multiple projects in the Loan Tracker monorepo.
Features
- Base Interfaces:
EventandModelinterfaces for type-safe event sourcing - Abstract Stores:
EventStoreandModelStorebase classes - In-Memory Implementations: Ready-to-use in-memory stores for testing
- Runtime Context Detection:
residence.isClientflag to differentiate between client and server behavior
Installation
This package is used internally within the monorepo. Reference it in your project's package.json:
{
"dependencies": {
"@loan-tracker/event-processor": "file:../event-processor"
}
}Usage
SDK Initialization (Recommended)
The event-processor SDK provides a centralized way to initialize all store implementations at once:
import {
initializeSDK,
getUserController,
getUIEventHandler,
StoreConfig
} from '@zeeshan60/event-processor';
import { MyUserModelStore } from './stores/MyUserModelStore';
import { MyUserEventStore } from './stores/MyUserEventStore';
// Initialize SDK once at app startup with ALL required stores
const sdk = initializeSDK({
userModelStore: new MyUserModelStore(),
userEventStore: new MyUserEventStore(),
friendModelStore: new MyFriendModelStore(),
friendEventStore: new MyFriendEventStore(),
transactionModelStore: new MyTransactionModelStore(),
transactionEventStore: new MyTransactionEventStore(),
groupModelStore: new MyGroupModelStore(),
groupEventStore: new MyGroupEventStore(),
groupTransactionModelStore: new MyGroupTransactionModelStore(),
groupTransactionEventStore: new MyGroupTransactionEventStore(),
activityLogModelStore: new MyActivityLogModelStore(),
activityLogEventStore: new MyActivityLogEventStore(),
});
// Use controllers anywhere in your app
const userController = getUserController();
const userId = await userController.loginUser(firebaseUid);
// Handle UI events
const uiEventHandler = getUIEventHandler();
await uiEventHandler.handleFirestoreEvent(eventData);For detailed SDK usage, see SDK_USAGE.md.
Basic Event Sourcing
import { Event, Model, InMemoryEventStore, InMemoryModelStore } from '@loan-tracker/event-processor';
// Define your event
class MyEvent implements Event {
constructor(
public userId: string,
public streamId: string,
public version: number
) {}
apply(existing: Model | null): Model {
// Your event application logic
return {
id: null,
userId: this.userId,
streamId: this.streamId,
version: this.version,
deleted: false
};
}
}
// Use the stores
const eventStore = new InMemoryEventStore();
const modelStore = new InMemoryModelStore();
// Store and apply events
await eventStore.addEvent(event);
const model = event.apply(null);
await modelStore.save(model);Runtime Context Configuration
The event-processor package uses the residence.isClient flag to differentiate between client and server execution contexts. This enables environment-specific behavior.
Quick Start
import { residence } from '@zeeshan60/event-processor';
// Client (Mobile App): No configuration needed - defaults to true
// The residence.isClient flag is true by default
// Google Cloud Functions: Set explicitly to false
residence.isClient = false;
// Check the runtime context
if (residence.isClient) {
console.log('Running in client application');
} else {
console.log('Running in Google Cloud Functions');
}Usage Pattern
Client (Mobile App):
// No setup needed - residence.isClient defaults to true
// Client creates events, applies to local modelsGoogle Cloud Functions:
import { residence } from '@zeeshan60/event-processor';
// Set at function initialization
residence.isClient = false;
// Server processes events, creates mirror events for other usersFor detailed context-specific behavior, see DUAL_CONTEXT_FLOW.md.
Documentation
📚 Essential Reading
- SDK_USAGE.md - 📦 Complete SDK initialization guide with examples and best practices
- DUAL_CONTEXT_FLOW.md - 🎯 START HERE! Comprehensive guide explaining how the package operates in client vs Google Cloud Functions contexts, complete with diagrams and examples
- QUICK_REFERENCE.md - Quick reference cheat sheet for common patterns, troubleshooting, and best practices
Why Dual-Context Matters
The event-processor package serves two distinct purposes:
- Client (Mobile App): Creates events from user actions, applies them to local models
- Google Cloud Functions: Processes events from Firestore, generates friend-perspective mirror events
Understanding when to create events vs when to process them is critical to avoid:
- Duplicate events
- Infinite loops
- Incorrect activity attribution
Read DUAL_CONTEXT_FLOW.md before integrating this package.
Architecture
- Event: Base interface for all events with
apply()method - Model: Base interface for all models/aggregates
- EventStore: Abstract class for event persistence
- ModelStore: Abstract class for model/read-model persistence
- residence: Runtime context object with
isClientflag for client vs server detection
Event Handlers
- TransactionEventHandler: Handles transaction lifecycle (create, update, delete)
- FriendEventHandler: Manages friend relationships
- UserEventHandler: Handles user profile changes
- GroupEventHandler: Manages group entities
- GroupTransactionEventHandler: Processes group transactions
- ActivityEventHandler: Creates activity log entries
Projects Using This Package
gcloud-functions: Google Cloud Functions backend (server-side event processing)mobile: Mobile application (client-side event creation)client-events: Client-side event definitions (extends this package)
