Shared event sourcing infrastructure for Loan Tracker projects
npm install @zeeshan60/event-processorShared event sourcing infrastructure for Loan Tracker projects.
This package provides the core building blocks for implementing event sourcing patterns across multiple projects in the Loan Tracker monorepo.
- Base Interfaces: Event and Model interfaces for type-safe event sourcing
- Abstract Stores: EventStore and ModelStore base classes
- In-Memory Implementations: Ready-to-use in-memory stores for testing
- Runtime Context Detection: residence.isClient flag to differentiate between client and server behavior
This package is used internally within the monorepo. Reference it in your project's package.json:
``json`
{
"dependencies": {
"@loan-tracker/event-processor": "file:../event-processor"
}
}
The event-processor SDK provides a centralized way to initialize all store implementations at once:
`typescript
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.
`typescript
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);
`
The event-processor package uses the residence.isClient flag to differentiate between client and server execution contexts. This enables environment-specific behavior.
`typescript
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');
}
`
Client (Mobile App):
`typescript`
// No setup needed - residence.isClient defaults to true
// Client creates events, applies to local models
Google Cloud Functions:
`typescript
import { residence } from '@zeeshan60/event-processor';
// Set at function initialization
residence.isClient = false;
// Server processes events, creates mirror events for other users
`
For detailed context-specific behavior, see DUAL_CONTEXT_FLOW.md.
- 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
The event-processor package serves two distinct purposes:
1. Client (Mobile App): Creates events from user actions, applies them to local models
2. 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.
- Event: Base interface for all events with apply() methodisClient
- 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 flag for client vs server detection
- 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
- 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)
-