Skip to main content

@happyvertical/smrt-events

Infinite-nesting event hierarchy with series, participant tracking, and recurrence patterns. Events can model anything from conferences with sessions to sports games with periods and goals.

Installation

pnpm add @happyvertical/smrt-events

Usage

Hierarchical events with participants

import { EventCollection, EventSeriesCollection, EventParticipantCollection } from '@happyvertical/smrt-events';

const events = await EventCollection.create();

// Create a game with nested periods
const game = await events.create({
name: 'Lakers vs Warriors',
slug: 'lakers-warriors-2024-01-20',
startDate: new Date('2024-01-20T19:30:00'),
endDate: new Date('2024-01-20T22:00:00'),
status: 'scheduled',
placeId: 'arena-id', // plain string FK to smrt-places
});

const quarter = await events.create({
name: '1st Quarter',
parentId: game.id, // infinite nesting (via SmrtHierarchical)
startDate: new Date('2024-01-20T19:30:00'),
});

// Hierarchy traversal
const hierarchy = await quarter.getHierarchy();
console.log(hierarchy.ancestors.map(e => e.name)); // ['Lakers vs Warriors']

// Add participants with roles and placement
const participants = await EventParticipantCollection.create();
await participants.create({
eventId: game.id,
profileId: 'lakers-id', // plain string FK to smrt-profiles
role: 'home',
placement: 0,
});

// Recurring series
const series = await EventSeriesCollection.create();
await series.create({
name: 'Weekly Standup',
slug: 'weekly-standup-2024',
recurrence: { frequency: 'weekly', interval: 1, byDay: ['MO', 'WE', 'FR'] },
});

Owned assets

import { AssetCollection } from '@happyvertical/smrt-assets';

const assets = await AssetCollection.create();
const hero = await assets.create({
name: 'launch-poster.jpg',
sourceUri: 'file:///tmp/launch-poster.jpg',
mimeType: 'image/jpeg',
});

await game.addAsset(hero, 'hero');
await events.addAsset(game.id!, hero, 'gallery', 1);

const heroAssets = await game.getAssets('hero');
const galleryAssets = await events.getAssets(game.id!, 'gallery');

API

Models

ExportDescription
EventHierarchical event with status lifecycle, STI enabled. Links to series, type, place via string IDs
EventSeriesRecurring event group with recurrence patterns (daily/weekly/monthly/yearly)
EventTypeClassification with JSON schema for custom fields per type
EventParticipantJunction linking profiles to events with role, placement, and groupId
EventAssetDedicated owned-asset join stored in event_assets with relationship and sortOrder

Collections

ExportDescription
EventCollectionCRUD + hierarchy traversal for events
EventAssetCollectionDirect access to event_assets rows plus asset helper wrappers
EventSeriesCollectionCRUD for event series
EventTypeCollectionCRUD for event types
EventParticipantCollectionCRUD for participants (conflictColumns: event_id, profile_id, role)

Types

ExportDescription
EventOptions, EventSeriesOptions, EventTypeOptions, EventParticipantOptionsCreation option types for each model
EventStatus'scheduled' | 'in_progress' | 'completed' | 'cancelled' | 'postponed'
ParticipantRoleRole values (speaker, home, away, organizer, etc.)
RecurrenceFrequency'daily' | 'weekly' | 'monthly' | 'yearly'
RecurrencePatternRecurrence definition with count, until, byDay, byMonth filters
EventSearchFilters, EventSeriesSearchFilters, ParticipantSearchFiltersQuery filter types

Utilities

ExportDescription
formatEventDateRangeFormat start/end dates as human-readable string
generateEventSlugCreate URL-friendly slug from name + date
checkSchedulingConflictDetect overlapping time ranges
calculateDurationDuration in milliseconds between two dates
formatDurationHuman-readable duration (e.g., "2h 30m")
isEventNowCheck if event is currently in progress
getEventStatusFromDatesAuto-detect status from start/end dates
sortEventsByDateSort events chronologically
validateEventStatusValidate status transition is allowed
calculateNextOccurrenceNext date for a recurrence pattern
parseRecurrencePatternParse recurrence from string or object

UI Metadata

ExportDescription
EVENTS_MODULE_METAModule metadata for UI registration
EVENTS_UI_SLOTSUI slot definitions for the events module

Instance Methods (Event)

getParent(), getChildren(), getAncestors(), getDescendants(), getRootEvent(), getHierarchy() -- hierarchy traversal on any Event instance.

Owned asset helpers are available on both Event and EventCollection via getAssets(), addAsset(), and removeAsset(). Common relationships include hero, gallery, attachment, and thumbnail.

Dependencies

PackagePurpose
@happyvertical/smrt-coreSmrtObject/SmrtCollection base classes
@happyvertical/smrt-tenancyOptional tenant scoping
@happyvertical/smrt-placesPlace references (cross-package string FKs)
@happyvertical/smrt-profilesParticipant profile references (cross-package string FKs)
@happyvertical/smrt-typesShared TypeScript types
@happyvertical/sqlDatabase operations
@happyvertical/aiAI integration