1- import { defineSchema } from "convex/server" ;
1+ // convex/schema.ts
2+ import { defineSchema , defineTable } from "convex/server" ;
23import { authTables } from "@convex-dev/auth/server" ;
3-
4- const schema = defineSchema ( {
4+ import { v } from "convex/values" ;
5+
6+ export default defineSchema ( {
57 ...authTables ,
6- // Your other tables...
8+
9+ // raw email data
10+ listservEmails : defineTable ( {
11+ listserv : v . string ( ) , // listserv name
12+ sentAt : v . number ( ) , // timestamp
13+ fromAddress : v . optional ( v . string ( ) ) , // listserv email address
14+ rawHtml : v . optional ( v . string ( ) ) ,
15+ rawText : v . optional ( v . string ( ) ) ,
16+ section : v . optional ( v . string ( ) ) , // "On-Campus", "Off-Campus", "Opportunities"
17+ } ) . index ( "by_listserv" , [ "listserv" ] ) ,
18+
19+ // One row per listserv item
20+ events : defineTable ( {
21+ listservEmailId : v . id ( "listservEmails" ) , // link to the listserv email data
22+ listserv : v . string ( ) ,
23+ listservSection : v . string ( ) ,
24+
25+ title : v . string ( ) ,
26+ description : v . string ( ) ,
27+ eventType : v . union (
28+ v . literal ( "event" ) , // one-time event
29+ v . literal ( "opportunity" ) , // internship, job, program, application
30+ v . literal ( "hackathon" ) ,
31+ v . literal ( "courses" ) , // workshop series / class series
32+ v . literal ( "fundraiser" ) ,
33+ v . literal ( "info" ) , // announcements with no clear CTA, catch-all
34+ ) ,
35+
36+ // ex. WICC x Jane Street, AppDev x Ramp, etc.
37+ hostClub : v . string ( ) , // primary org (maps to a clubs table eventually)
38+ coHosts : v . array ( v . string ( ) ) , // ["Ramp"], [] if none
39+
40+ dates : v . array (
41+ v . object ( {
42+ timestamp : v . number ( ) ,
43+ type : v . union (
44+ v . literal ( "start" ) , // start & end for recurring events
45+ v . literal ( "end" ) ,
46+ v . literal ( "deadline" ) ,
47+ v . literal ( "single" ) , // one-off event with no end
48+ ) ,
49+ } ) ,
50+ ) ,
51+ isRecurring : v . boolean ( ) ,
52+ recurrenceNote : v . optional ( v . string ( ) ) , // "Every Wednesday 5-6:30pm"
53+
54+ location : v . optional (
55+ v . object ( {
56+ displayText : v . string ( ) ,
57+ address : v . optional ( v . string ( ) ) ,
58+ isVirtual : v . boolean ( ) ,
59+ buildingCode : v . optional ( v . string ( ) ) , // "Gates 114", "CIS 250"
60+ } ) ,
61+ ) ,
62+
63+ links : v . array (
64+ v . object ( {
65+ url : v . string ( ) ,
66+ type : v . union (
67+ v . literal ( "registration" ) , // more for courses, hackathons, etc.
68+ v . literal ( "application" ) , // internships, jobs, programs
69+ v . literal ( "rsvp" ) , // events with physical link (decide if combines with registration)
70+ v . literal ( "info" ) , // general info, websites, etc.
71+ v . literal ( "social" ) , // instagram, etc.
72+ ) ,
73+ label : v . optional ( v . string ( ) ) , // "Apply here", "RSVP Link"
74+ } ) ,
75+ ) ,
76+
77+ contacts : v . array (
78+ v . object ( {
79+ type : v . union (
80+ v . literal ( "email" ) ,
81+ v . literal ( "instagram" ) ,
82+ v . literal ( "website" ) ,
83+ ) ,
84+ value : v . string ( ) ,
85+ } ) ,
86+ ) ,
87+
88+ tags : v . array ( v . string ( ) ) ,
89+ targetAudience : v . optional (
90+ v . union ( // decide if we need all or define more
91+ v . literal ( "all" ) ,
92+ v . literal ( "first_year" ) ,
93+ v . literal ( "women_nonbinary" ) ,
94+ v . literal ( "international" ) ,
95+ v . literal ( "graduate" ) ,
96+ ) ,
97+ ) ,
98+ perks : v . array (
99+ v . union (
100+ v . literal ( "food" ) ,
101+ v . literal ( "swag" ) ,
102+ v . literal ( "prizes" ) ,
103+ v . literal ( "travel_covered" ) ,
104+ v . literal ( "paid" ) ,
105+ ) ,
106+ ) ,
107+
108+ } )
109+ . index ( "by_listserv" , [ "listserv" ] )
110+ . index ( "by_section" , [ "listservSection" ] )
111+ . index ( "by_event_type" , [ "eventType" ] )
112+ . index ( "by_host" , [ "hostClub" ] ) ,
7113} ) ;
8-
9- export default schema ;
0 commit comments