Skip to content

Event Code Examples

Triggering Events via API

Frontend applications do not publish events directly. Instead, they perform actions via the REST API, which automatically publishes the corresponding domain events on the backend.

Example 1: Triggering "User Followed" Event

When you call the follow endpoint, the API publishes user.followed_user.

javascript
// Frontend Code
const handleFollowUser = async (followedUserId) => {
  try {
    // API call triggers the event on the backend
    await fetch(`https://api.fundlyhub.org/api/v1/users/${followedUserId}/follow`, {
      method: 'POST',
      credentials: 'include'
    });
    
    toast.success('User followed successfully');
  } catch (error) {
    console.error('Failed to follow user:', error);
  }
};

Example 2: Triggering "Campaign Created" Event

Creating a campaign triggers campaign.created and starts the creation saga.

javascript
// Frontend Code
const handleCreateCampaign = async (campaignData) => {
  try {
    const response = await fetch('https://api.fundlyhub.org/api/v1/fundraisers', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json'
      },
      credentials: 'include',
      body: JSON.stringify(campaignData)
    });

    if (!response.ok) throw new Error('Creation failed');

    // The backend has now published 'campaign.created'
    const campaign = await response.json();
    navigate(`/campaigns/${campaign.slug}`);
  } catch (error) {
    console.error('Failed to create campaign:', error);
  }
};

Backend Event Processing

Events are processed asynchronously by backend workers. Here is how a processor handles an event:

Example: Email Notification Processor

typescript
// Backend Code (Node.js Processor)


export class EmailNotificationProcessor {
  constructor() {
    EventBus.subscribe('user.followed_user', this.handle.bind(this));
  }

  async handle(event) {
    const { followerId, followedUserId } = event.payload;

    // Idempotency check
    if (await this.isProcessed(event.id)) return;

    try {
      // Get user details
      const user = await UserRepository.findById(followedUserId);
      const follower = await UserRepository.findById(followerId);

      // Send email
      await EmailService.send({
        to: user.email,
        subject: 'You have a new follower!',
        template: 'new_follower',
        context: {
          userName: user.name,
          followerName: follower.name
        }
      });

      console.log(`Email sent for event ${event.id}`);
      await this.markProcessed(event.id);
    } catch (error) {
      console.error('Failed to process email notification:', error);
    }
  }
}

Testing Events (Backend)

Integration tests verify that API calls trigger the correct events:

typescript
import { request } from 'supertest';


describe('Follow User Flow', () => {
  it('should publish user.followed_user event', async () => {
    // 1. Make API call
    await request(app)
      .post('/api/v1/users/user-123/follow')
      .set('Cookie', `session=${sessionCookie}`)
      .expect(200);

    // 2. Verify event was published to store
    const events = await EventStore.findEvents({
      type: 'user.followed_user',
      payload: { followedUserId: 'user-123' }
    });

    expect(events.length).toBe(1);
    expect(events[0].payload.followerId).toBe(testUser.id);
  });
});

Built with VitePress