generator client { provider = "prisma-client-js" } datasource db { provider = "postgresql" url = env("DATABASE_URL") } model User { id String @id @default(cuid()) did String @unique username String? createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") eventSources EventSource[] events Event[] @@map("users") } // External event source (Luma, Meetup, iCal feed, manual, etc.) model EventSource { id String @id @default(cuid()) name String sourceType String @map("source_type") // luma, meetup, ical, manual, rss color String @default("#6b7280") isActive Boolean @default(true) @map("is_active") // Connection config (API key, feed URL, org slug, etc.) config Json @default("{}") lastSyncedAt DateTime? @map("last_synced_at") lastSyncError String @default("") @map("last_sync_error") eventCount Int @default(0) @map("event_count") createdById String @map("created_by_id") createdBy User @relation(fields: [createdById], references: [id]) // Space scoping spaceSlug String? @map("space_slug") createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") events Event[] @@index([createdById]) @@index([spaceSlug]) @@map("event_sources") } model Event { id String @id @default(cuid()) sourceId String @map("source_id") externalId String @default("") @map("external_id") externalUrl String @default("") @map("external_url") // Core title String description String @default("") start DateTime end DateTime allDay Boolean @default(false) @map("all_day") timezoneStr String @default("UTC") @map("timezone_str") rrule String @default("") isRecurring Boolean @default(false) @map("is_recurring") // Location locationName String @default("") @map("location_name") locationAddress String @default("") @map("location_address") latitude Float? longitude Float? isVirtual Boolean @default(false) @map("is_virtual") virtualUrl String @default("") @map("virtual_url") virtualPlatform String @default("") @map("virtual_platform") // Organizer / participants organizerName String @default("") @map("organizer_name") organizerEmail String @default("") @map("organizer_email") organizerUrl String @default("") @map("organizer_url") attendeeCount Int @default(0) @map("attendee_count") maxAttendees Int? @map("max_attendees") rsvpUrl String @default("") @map("rsvp_url") // Categorization status String @default("confirmed") // confirmed, tentative, cancelled visibility String @default("public") category String @default("") // conference, meetup, workshop, social, etc. tags String[] @default([]) imageUrl String @default("") @map("image_url") cost String @default("") // free, $10, etc. // rStack integration rToolSource String? @map("r_tool_source") // e.g. "rcal", "rinbox" rToolEntityId String? @map("r_tool_entity_id") syncedToRcal Boolean @default(false) @map("synced_to_rcal") metadata Json? // Ownership createdById String? @map("created_by_id") createdBy User? @relation(fields: [createdById], references: [id]) spaceSlug String? @map("space_slug") // Timestamps createdAt DateTime @default(now()) @map("created_at") updatedAt DateTime @updatedAt @map("updated_at") // Relations source EventSource @relation(fields: [sourceId], references: [id], onDelete: Cascade) @@unique([sourceId, externalId]) @@index([sourceId]) @@index([start, end]) @@index([spaceSlug]) @@index([category]) @@index([rToolSource, rToolEntityId]) @@map("events") }