summaryrefslogtreecommitdiff
path: root/backend/src
diff options
context:
space:
mode:
Diffstat (limited to 'backend/src')
-rw-r--r--backend/src/data/events.json162
-rw-r--r--backend/src/data/rsvps.json452
-rw-r--r--backend/src/data/users.json152
-rw-r--r--backend/src/db.js72
-rw-r--r--backend/src/routes/api.js12
-rw-r--r--backend/src/routes/events.js97
-rw-r--r--backend/src/routes/users.js65
-rw-r--r--backend/src/server.js40
8 files changed, 1052 insertions, 0 deletions
diff --git a/backend/src/data/events.json b/backend/src/data/events.json
new file mode 100644
index 0000000..da5b0a9
--- /dev/null
+++ b/backend/src/data/events.json
@@ -0,0 +1,162 @@
+[
+ {
+ "id": "1",
+ "title": "Community Thanksgiving Potluck",
+ "date": "2025-11-29",
+ "image_url": "https://images.unsplash.com/photo-1574672280600-4accfa5b6f98?w=500",
+ "description": "Join our annual community feast! Bring your favorite dish to share and celebrate gratitude with neighbors. All are welcome to this warm gathering of food and friendship.",
+ "host_id": "1"
+ },
+ {
+ "id": "2",
+ "title": "Solstice Celebration",
+ "date": "2025-12-21",
+ "image_url": "https://images.unsplash.com/photo-1482517967863-00e15c9b44be?w=500",
+ "description": "Welcome the winter solstice with music, meditation, and seasonal ceremonies. Experience the magic of the longest night of the year in community.",
+ "host_id": "2"
+ },
+ {
+ "id": "3",
+ "title": "EventExpo 2026",
+ "date": "2026-04-01",
+ "image_url": "https://images.unsplash.com/photo-1511578314322-379afb476865?w=500",
+ "description": "Discover the future of event planning at EventExpo 2026. Network with industry leaders, explore cutting-edge technologies, and attend inspiring workshops.",
+ "host_id": "3"
+ },
+ {
+ "id": "4",
+ "title": "Critical Mass Bike Ride",
+ "date": "2025-09-25",
+ "image_url": "https://images.unsplash.com/photo-1593259525326-ef1511674267?w=500",
+ "description": "Take back the streets in this monthly community bike ride. Promote cycling awareness and safety while enjoying a scenic tour through the city with fellow cyclists.",
+ "host_id": "4"
+ },
+ {
+ "id": "5",
+ "title": "New Year Celebration",
+ "date": "2026-01-01",
+ "image_url": "https://images.unsplash.com/photo-1521478413868-1bbd982fa4a5?q=80&w=500&auto=format&fit=crop&ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D",
+ "description": "Celebrate the start of the new year with fireworks, music, and community festivities.",
+ "host_id": "5"
+ },
+ {
+ "id": "6",
+ "title": "Summer Music Festival",
+ "date": "2025-07-15",
+ "image_url": "https://images.unsplash.com/photo-1589553975453-d7e36c7cfbf8?w=500",
+ "description": "Enjoy a day of live music, food trucks, and fun activities at the annual Summer Music Festival.",
+ "host_id": "2"
+ },
+ {
+ "id": "7",
+ "title": "Tech Startup Meetup",
+ "date": "2025-09-15",
+ "image_url": "https://images.unsplash.com/photo-1515187029135-18ee286d815b?w=500",
+ "description": "Connect with fellow entrepreneurs, developers, and investors. Share ideas, get feedback, and build meaningful relationships in the tech community.",
+ "host_id": "6"
+ },
+ {
+ "id": "8",
+ "title": "Yoga in the Park",
+ "date": "2025-08-08",
+ "image_url": "https://images.unsplash.com/photo-1544367567-0f2fcb009e0b?w=500",
+ "description": "Start your day with a refreshing yoga session in the beautiful city park. All skill levels welcome. Don't forget to bring your mat!",
+ "host_id": "7"
+ },
+ {
+ "id": "9",
+ "title": "Art Gallery Opening",
+ "date": "2025-10-14",
+ "image_url": "https://images.unsplash.com/photo-1541961017774-22349e4a1262?w=500",
+ "description": "Join us for the opening of 'Urban Perspectives' featuring local artists. Enjoy wine, hors d'oeuvres, and engaging conversations about contemporary art.",
+ "host_id": "8"
+ },
+ {
+ "id": "10",
+ "title": "Cooking Class: Mediterranean Cuisine",
+ "date": "2025-09-28",
+ "image_url": "https://images.unsplash.com/photo-1556909114-f6e7ad7d3136?w=500",
+ "description": "Learn to cook authentic Mediterranean dishes from scratch. Includes ingredients, recipes, and a delicious meal to enjoy together.",
+ "host_id": "9"
+ },
+ {
+ "id": "11",
+ "title": "Book Club: Science Fiction",
+ "date": "2025-08-20",
+ "image_url": "https://images.unsplash.com/photo-1481627834876-b7833e8f5570?w=500",
+ "description": "Discuss this month's selection: 'The Three-Body Problem' by Liu Cixin. Coffee and snacks provided. New members always welcome!",
+ "host_id": "10"
+ },
+ {
+ "id": "12",
+ "title": "Photography Workshop",
+ "date": "2025-11-22",
+ "image_url": "https://images.unsplash.com/photo-1516035069371-29a1b244cc32?w=500",
+ "description": "Master the basics of digital photography. Learn composition, lighting, and editing techniques. Bring your camera or smartphone.",
+ "host_id": "11"
+ },
+ {
+ "id": "13",
+ "title": "Language Exchange: Spanish/English",
+ "date": "2025-09-10",
+ "image_url": "https://images.unsplash.com/photo-1546410531-bb4caa6b424d?w=500",
+ "description": "Practice Spanish and English in a friendly, conversational setting. All levels welcome. Coffee and light refreshments included.",
+ "host_id": "12"
+ },
+ {
+ "id": "14",
+ "title": "Board Game Night",
+ "date": "2025-10-08",
+ "image_url": "https://images.unsplash.com/photo-1610890716171-6b1bb98ffd09?w=500",
+ "description": "Join us for an evening of strategy, fun, and friendly competition. We'll have a variety of games for all skill levels.",
+ "host_id": "13"
+ },
+ {
+ "id": "15",
+ "title": "Hiking Adventure",
+ "date": "2025-07-12",
+ "image_url": "https://images.unsplash.com/photo-1551632811-561732d1e306?w=500",
+ "description": "Explore the beautiful mountain trails with our experienced guide. Moderate difficulty, 4-hour hike with stunning views.",
+ "host_id": "14"
+ },
+ {
+ "id": "16",
+ "title": "Jazz Night at the Lounge",
+ "date": "2025-09-25",
+ "image_url": "https://images.unsplash.com/photo-1493225457124-a3eb161ffa5f?w=500",
+ "description": "Enjoy live jazz music in an intimate setting. Featuring local musicians and craft cocktails. Reservations recommended.",
+ "host_id": "15"
+ },
+ {
+ "id": "17",
+ "title": "Volunteer Day: Community Garden",
+ "date": "2025-10-15",
+ "image_url": "https://images.unsplash.com/photo-1416879595882-3373a0480b5b?w=500",
+ "description": "Help maintain our community garden. Tasks include planting, weeding, and general maintenance. Tools provided, bring work gloves.",
+ "host_id": "16"
+ },
+ {
+ "id": "18",
+ "title": "Film Screening: Documentary Night",
+ "date": "2025-08-15",
+ "image_url": "https://images.unsplash.com/photo-1489599835382-957593cb2371?w=500",
+ "description": "Watch and discuss thought-provoking documentaries about environmental conservation. Popcorn and refreshments provided.",
+ "host_id": "17"
+ },
+ {
+ "id": "19",
+ "title": "Dance Workshop: Salsa Basics",
+ "date": "2025-09-18",
+ "image_url": "https://images.unsplash.com/photo-1504609773096-104ff2c73ba4?w=500",
+ "description": "Learn the fundamentals of salsa dancing in a fun, beginner-friendly environment. No partner required, comfortable shoes recommended.",
+ "host_id": "18"
+ },
+ {
+ "id": "20",
+ "title": "Craft Fair & Market",
+ "date": "2025-12-05",
+ "image_url": "https://images.unsplash.com/photo-1441986300917-64674bd600d8?w=500",
+ "description": "Support local artisans and discover unique handmade goods. Food trucks, live music, and family-friendly activities throughout the day.",
+ "host_id": "19"
+ }
+] \ No newline at end of file
diff --git a/backend/src/data/rsvps.json b/backend/src/data/rsvps.json
new file mode 100644
index 0000000..eb9c868
--- /dev/null
+++ b/backend/src/data/rsvps.json
@@ -0,0 +1,452 @@
+[
+ {
+ "event_id": 1,
+ "name": "Carlos Mendoza",
+ "email": "carlos.mendoza@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Yuki Tanaka",
+ "email": "yuki.tanaka@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Mohammed Ali",
+ "email": "mohammed.ali@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Amina Jafari",
+ "email": "amina.jafari@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Ravi Kumar",
+ "email": "ravi.kumar@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "event_id": 1,
+ "name": "Alex Thompson",
+ "email": "alex.thompson@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Aisha Khan",
+ "email": "aisha.khan@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Chloe Dubois",
+ "email": "chloe.dubois@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Nia Mwangi",
+ "email": "nia.mwangi@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Kofi Mensah",
+ "email": "kofi.mensah@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Tariq Aziz",
+ "email": "tariq.aziz@example.com"
+ },
+ {
+ "event_id": 2,
+ "name": "Maria Rodriguez",
+ "email": "maria.rodriguez@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "Liam O'Connor",
+ "email": "liam.oconnor@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "Santiago Garcia",
+ "email": "santiago.garcia@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "Priya Singh",
+ "email": "priya.singh@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "Elena Petrova",
+ "email": "elena.petrova@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "event_id": 3,
+ "name": "Lisa Park",
+ "email": "lisa.park@example.com"
+ },
+ {
+ "event_id": 4,
+ "name": "Fatima Al-Sayed",
+ "email": "fatima.alsayed@example.com"
+ },
+ {
+ "event_id": 4,
+ "name": "Omar Faruk",
+ "email": "omar.faruk@example.com"
+ },
+ {
+ "event_id": 4,
+ "name": "Lina Chen",
+ "email": "lina.chen@example.com"
+ },
+ {
+ "event_id": 4,
+ "name": "Jamal Carter",
+ "email": "jamal.carter@example.com"
+ },
+ {
+ "event_id": 4,
+ "name": "David Johnson",
+ "email": "david.johnson@example.com"
+ },
+ {
+ "event_id": 5,
+ "name": "Raj Patel",
+ "email": "raj.patel@example.com"
+ },
+ {
+ "event_id": 5,
+ "name": "Zara Khan",
+ "email": "zara.khan@example.com"
+ },
+ {
+ "event_id": 5,
+ "name": "Sofia Martinez",
+ "email": "sofia.martinez@example.com"
+ },
+ {
+ "event_id": 5,
+ "name": "Emma Wilson",
+ "email": "emma.wilson@example.com"
+ },
+ {
+ "event_id": 6,
+ "name": "Sofia Rossi",
+ "email": "sofia.rossi@example.com"
+ },
+ {
+ "event_id": 6,
+ "name": "Emma Wilson",
+ "email": "emma.wilson@example.com"
+ },
+ {
+ "event_id": 6,
+ "name": "Liam Smith",
+ "email": "liam.smith@example.com"
+ },
+ {
+ "event_id": 6,
+ "name": "Nina Schmidt",
+ "email": "nina.schmidt@example.com"
+ },
+ {
+ "event_id": 6,
+ "name": "Marcus Johnson",
+ "email": "marcus.johnson@example.com"
+ },
+ {
+ "event_id": 7,
+ "name": "Alex Thompson",
+ "email": "alex.thompson@example.com"
+ },
+ {
+ "event_id": 7,
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "event_id": 7,
+ "name": "Lisa Park",
+ "email": "lisa.park@example.com"
+ },
+ {
+ "event_id": 7,
+ "name": "Elena Petrova",
+ "email": "elena.petrova@example.com"
+ },
+ {
+ "event_id": 8,
+ "name": "Yuki Tanaka",
+ "email": "yuki.tanaka@example.com"
+ },
+ {
+ "event_id": 8,
+ "name": "Chloe Dubois",
+ "email": "chloe.dubois@example.com"
+ },
+ {
+ "event_id": 8,
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "event_id": 8,
+ "name": "Nina Schmidt",
+ "email": "nina.schmidt@example.com"
+ },
+ {
+ "event_id": 9,
+ "name": "Priya Singh",
+ "email": "priya.singh@example.com"
+ },
+ {
+ "event_id": 9,
+ "name": "Maria Rodriguez",
+ "email": "maria.rodriguez@example.com"
+ },
+ {
+ "event_id": 9,
+ "name": "Lina Chen",
+ "email": "lina.chen@example.com"
+ },
+ {
+ "event_id": 9,
+ "name": "Sofia Garcia",
+ "email": "sofia.garcia@example.com"
+ },
+ {
+ "event_id": 10,
+ "name": "Carlos Mendoza",
+ "email": "carlos.mendoza@example.com"
+ },
+ {
+ "event_id": 10,
+ "name": "Fatima Al-Farsi",
+ "email": "fatima.alfarsi@example.com"
+ },
+ {
+ "event_id": 10,
+ "name": "Omar Faruk",
+ "email": "omar.faruk@example.com"
+ },
+ {
+ "event_id": 10,
+ "name": "Tariq Aziz",
+ "email": "tariq.aziz@example.com"
+ },
+ {
+ "event_id": 11,
+ "name": "Liam O'Connor",
+ "email": "liam.oconnor@example.com"
+ },
+ {
+ "event_id": 11,
+ "name": "Ravi Kumar",
+ "email": "ravi.kumar@example.com"
+ },
+ {
+ "event_id": 11,
+ "name": "Elena Petrova",
+ "email": "elena.petrova@example.com"
+ },
+ {
+ "event_id": 11,
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "event_id": 12,
+ "name": "Yuki Tanaka",
+ "email": "yuki.tanaka@example.com"
+ },
+ {
+ "event_id": 12,
+ "name": "Lina Chen",
+ "email": "lina.chen@example.com"
+ },
+ {
+ "event_id": 12,
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "event_id": 12,
+ "name": "Alex Thompson",
+ "email": "alex.thompson@example.com"
+ },
+ {
+ "event_id": 13,
+ "name": "Sofia Garcia",
+ "email": "sofia.garcia@example.com"
+ },
+ {
+ "event_id": 13,
+ "name": "Carlos Mendoza",
+ "email": "carlos.mendoza@example.com"
+ },
+ {
+ "event_id": 13,
+ "name": "Maria Rodriguez",
+ "email": "maria.rodriguez@example.com"
+ },
+ {
+ "event_id": 13,
+ "name": "Omar Faruk",
+ "email": "omar.faruk@example.com"
+ },
+ {
+ "event_id": 14,
+ "name": "Jamal Carter",
+ "email": "jamal.carter@example.com"
+ },
+ {
+ "event_id": 14,
+ "name": "David Johnson",
+ "email": "david.johnson@example.com"
+ },
+ {
+ "event_id": 14,
+ "name": "Marcus Johnson",
+ "email": "marcus.johnson@example.com"
+ },
+ {
+ "event_id": 14,
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "event_id": 15,
+ "name": "Kofi Mensah",
+ "email": "kofi.mensah@example.com"
+ },
+ {
+ "event_id": 15,
+ "name": "Nia Mwangi",
+ "email": "nia.mwangi@example.com"
+ },
+ {
+ "event_id": 15,
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "event_id": 15,
+ "name": "Alex Thompson",
+ "email": "alex.thompson@example.com"
+ },
+ {
+ "event_id": 16,
+ "name": "Nina Schmidt",
+ "email": "nina.schmidt@example.com"
+ },
+ {
+ "event_id": 16,
+ "name": "Chloe Dubois",
+ "email": "chloe.dubois@example.com"
+ },
+ {
+ "event_id": 16,
+ "name": "Emma Wilson",
+ "email": "emma.wilson@example.com"
+ },
+ {
+ "event_id": 16,
+ "name": "Lisa Park",
+ "email": "lisa.park@example.com"
+ },
+ {
+ "event_id": 17,
+ "name": "Fatima Al-Farsi",
+ "email": "fatima.alfarsi@example.com"
+ },
+ {
+ "event_id": 17,
+ "name": "Omar Faruk",
+ "email": "omar.faruk@example.com"
+ },
+ {
+ "event_id": 17,
+ "name": "Tariq Aziz",
+ "email": "tariq.aziz@example.com"
+ },
+ {
+ "event_id": 17,
+ "name": "Carlos Mendoza",
+ "email": "carlos.mendoza@example.com"
+ },
+ {
+ "event_id": 18,
+ "name": "Elena Petrova",
+ "email": "elena.petrova@example.com"
+ },
+ {
+ "event_id": 18,
+ "name": "Ravi Kumar",
+ "email": "ravi.kumar@example.com"
+ },
+ {
+ "event_id": 18,
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "event_id": 18,
+ "name": "Liam O'Connor",
+ "email": "liam.oconnor@example.com"
+ },
+ {
+ "event_id": 19,
+ "name": "Sofia Garcia",
+ "email": "sofia.garcia@example.com"
+ },
+ {
+ "event_id": 19,
+ "name": "Maria Rodriguez",
+ "email": "maria.rodriguez@example.com"
+ },
+ {
+ "event_id": 19,
+ "name": "Chloe Dubois",
+ "email": "chloe.dubois@example.com"
+ },
+ {
+ "event_id": 19,
+ "name": "Nina Schmidt",
+ "email": "nina.schmidt@example.com"
+ },
+ {
+ "event_id": 20,
+ "name": "Emma Wilson",
+ "email": "emma.wilson@example.com"
+ },
+ {
+ "event_id": 20,
+ "name": "Lisa Park",
+ "email": "lisa.park@example.com"
+ },
+ {
+ "event_id": 20,
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "event_id": 20,
+ "name": "Yuki Tanaka",
+ "email": "yuki.tanaka@example.com"
+ },
+ {
+ "event_id": 20,
+ "name": "Lina Chen",
+ "email": "lina.chen@example.com"
+ }
+] \ No newline at end of file
diff --git a/backend/src/data/users.json b/backend/src/data/users.json
new file mode 100644
index 0000000..0615d81
--- /dev/null
+++ b/backend/src/data/users.json
@@ -0,0 +1,152 @@
+[
+ {
+ "id": 1,
+ "username": "amina",
+ "name": "Amina Khan",
+ "email": "amina.khan@example.com"
+ },
+ {
+ "id": 2,
+ "username": "liam",
+ "name": "Liam O'Connor",
+ "email": "liam.oconnor@example.com"
+ },
+ {
+ "id": 3,
+ "username": "sofia",
+ "name": "Sofia Garcia",
+ "email": "sofia.garcia@example.com"
+ },
+ {
+ "id": 4,
+ "username": "raj",
+ "name": "Raj Patel",
+ "email": "raj.patel@example.com"
+ },
+ {
+ "id": 5,
+ "username": "fatima",
+ "name": "Fatima Al-Farsi",
+ "email": "fatima.alfarsi@example.com"
+ },
+ {
+ "id": 6,
+ "username": "marcus",
+ "name": "Marcus Johnson",
+ "email": "marcus.johnson@example.com"
+ },
+ {
+ "id": 7,
+ "username": "yuki",
+ "name": "Yuki Tanaka",
+ "email": "yuki.tanaka@example.com"
+ },
+ {
+ "id": 8,
+ "username": "priya",
+ "name": "Priya Singh",
+ "email": "priya.singh@example.com"
+ },
+ {
+ "id": 9,
+ "username": "carlos",
+ "name": "Carlos Mendoza",
+ "email": "carlos.mendoza@example.com"
+ },
+ {
+ "id": 10,
+ "username": "emma",
+ "name": "Emma Wilson",
+ "email": "emma.wilson@example.com"
+ },
+ {
+ "id": 11,
+ "username": "omar",
+ "name": "Omar Faruk",
+ "email": "omar.faruk@example.com"
+ },
+ {
+ "id": 12,
+ "username": "lina",
+ "name": "Lina Chen",
+ "email": "lina.chen@example.com"
+ },
+ {
+ "id": 13,
+ "username": "david",
+ "name": "David Johnson",
+ "email": "david.johnson@example.com"
+ },
+ {
+ "id": 14,
+ "username": "chloe",
+ "name": "Chloe Dubois",
+ "email": "chloe.dubois@example.com"
+ },
+ {
+ "id": 15,
+ "username": "kofi",
+ "name": "Kofi Mensah",
+ "email": "kofi.mensah@example.com"
+ },
+ {
+ "id": 16,
+ "username": "elena",
+ "name": "Elena Petrova",
+ "email": "elena.petrova@example.com"
+ },
+ {
+ "id": 17,
+ "username": "jamal",
+ "name": "Jamal Carter",
+ "email": "jamal.carter@example.com"
+ },
+ {
+ "id": 18,
+ "username": "nina",
+ "name": "Nina Schmidt",
+ "email": "nina.schmidt@example.com"
+ },
+ {
+ "id": 19,
+ "username": "ravi",
+ "name": "Ravi Kumar",
+ "email": "ravi.kumar@example.com"
+ },
+ {
+ "id": 20,
+ "username": "tariq",
+ "name": "Tariq Aziz",
+ "email": "tariq.aziz@example.com"
+ },
+ {
+ "id": 21,
+ "username": "sarah",
+ "name": "Sarah Mitchell",
+ "email": "sarah.mitchell@example.com"
+ },
+ {
+ "id": 22,
+ "username": "alex",
+ "name": "Alex Thompson",
+ "email": "alex.thompson@example.com"
+ },
+ {
+ "id": 23,
+ "username": "maria",
+ "name": "Maria Rodriguez",
+ "email": "maria.rodriguez@example.com"
+ },
+ {
+ "id": 24,
+ "username": "james",
+ "name": "James Anderson",
+ "email": "james.anderson@example.com"
+ },
+ {
+ "id": 25,
+ "username": "lisa",
+ "name": "Lisa Park",
+ "email": "lisa.park@example.com"
+ }
+] \ No newline at end of file
diff --git a/backend/src/db.js b/backend/src/db.js
new file mode 100644
index 0000000..f20cac1
--- /dev/null
+++ b/backend/src/db.js
@@ -0,0 +1,72 @@
+import Database from 'better-sqlite3';
+import EVENTS from './data/events.json' with {type: 'json'};
+import USERS from './data/users.json' with {type: 'json'};
+import RSVPS from './data/rsvps.json' with {type: 'json'};
+
+
+const db = new Database('src/sqlite.db', { verbose: console.log });
+
+console.log(`Initializing database: ${db.name} `);
+
+
+db.pragma('foreign_keys = ON');
+
+
+db.exec(`
+ CREATE TABLE IF NOT EXISTS users (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ username TEXT NOT NULL UNIQUE,
+ name TEXT NOT NULL,
+ email TEXT
+ );
+ `);
+db.exec(`
+ CREATE TABLE IF NOT EXISTS events (
+ id INTEGER PRIMARY KEY,
+ title TEXT NOT NULL,
+ description TEXT,
+ image_url TEXT,
+ date DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
+ host_id INTEGER REFERENCES users NOT NULL
+ );
+ CREATE INDEX IF NOT EXISTS eventhosts ON events(host_id);
+ `);
+
+
+const upsertUser = db.prepare(`
+ INSERT INTO users VALUES (@id, @username, @name, @email)
+ ON CONFLICT(id) DO NOTHING
+ `)
+
+USERS.map((user) => upsertUser.run(user));
+
+const upsertEvent = db.prepare(`
+ INSERT INTO events VALUES (@id, @title, @description, @image_url, @date, @host_id)
+ ON CONFLICT(id) DO NOTHING
+ `)
+
+EVENTS.map((event) => {
+ upsertEvent.run(event);
+});
+
+
+db.exec(`
+ CREATE TABLE IF NOT EXISTS rsvps (
+ event_id INTEGER REFERENCES events NOT NULL,
+ name TEXT NOT NULL,
+ email TEXT NOT NULL,
+ UNIQUE(event_id, email) ON CONFLICT REPLACE
+ );
+ CREATE INDEX IF NOT EXISTS rsvpevents ON rsvps(event_id);
+`);
+
+const upsertRSVP = db.prepare(`
+ INSERT INTO rsvps VALUES (@event_id, @name, @email)
+`);
+RSVPS.map((rsvp) => {
+ upsertRSVP.run(rsvp);
+});
+
+
+
+export default db; \ No newline at end of file
diff --git a/backend/src/routes/api.js b/backend/src/routes/api.js
new file mode 100644
index 0000000..2eb07d1
--- /dev/null
+++ b/backend/src/routes/api.js
@@ -0,0 +1,12 @@
+import { Router } from 'express';
+import usersRouter from './users.js';
+import eventsRouter from './events.js';
+
+
+const router = Router();
+
+router.use('/users', usersRouter);
+router.use('/events', eventsRouter);
+
+
+export default router;
diff --git a/backend/src/routes/events.js b/backend/src/routes/events.js
new file mode 100644
index 0000000..b95c747
--- /dev/null
+++ b/backend/src/routes/events.js
@@ -0,0 +1,97 @@
+import db from '../db.js';
+import { Router } from 'express';
+import { getUser } from './users.js';
+
+const router = Router();
+
+const joinHost = (event) => {
+ const host = getUser(event.host_id);
+ return { ...event, host };
+}
+
+const joinRSVPs = (event) => {
+ const { id } = event;
+ const getRSVPs = db.prepare('SELECT * FROM rsvps WHERE event_id = @id');
+ const rsvps = getRSVPs.all({ id });
+ return { ...event, rsvps };
+}
+
+const getEvent = (eventId) => {
+ const byId = db.prepare('SELECT * FROM events WHERE id = @eventId');
+ const event = byId.get({ eventId });
+ return joinHost(event);
+}
+
+router.get('/', (_req, res) => {
+ const listEvents = db.prepare(`SELECT * FROM events`);
+ const events = listEvents.all();
+ res.json(events.map(joinHost).map(joinRSVPs));
+});
+
+const insertEvent = db.prepare(`INSERT INTO events VALUES (@id, @title, @description, @image_url, @date, @host_id)`);
+
+router.post('/new', (req, res) => {
+ const data = req.body;
+ const { lastInsertRowid: id } = insertEvent.run(data);
+ const event = getEvent(id);
+ res.status(201).json(event);
+});
+
+router.get('/:id', (req, res) => {
+ const id = parseInt(req.params.id);
+ const event = getEvent(id);
+ if (!event) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ res.json(event);
+});
+
+router.patch('/:id', (req, res) => {
+ const eventId = parseInt(req.params.id);
+ const patch = req.body;
+
+ const updateCol = db.prepare(`
+ UPDATE events SET @col = @val WHERE id = @eventId
+ `);
+ const updateEvent = db.transaction((patch) => {
+ for (const [col, val] of Object.entries(patch)) {
+ updateCol.run({ col, val, eventId });
+ }
+ });
+
+ updateEvent(Object.entries(patch));
+ const updated = getEvent(eventId);
+ res.json(updated);
+});
+
+router.delete('/:id', (req, res) => {
+ const deleteEvent = db.prepare(`DELETE FROM events WHERE id = @eventId`);
+ const eventId = parseInt(req.params.id);
+ const event = getEvent(eventId);
+ if (!event) {
+ return res.status(404).json({ error: 'Event not found' });
+ }
+ deleteEvent.run({ eventId });
+ res.json(event);
+});
+
+router.post('/:id/rsvp', (req, res) => {
+ const eventId = parseInt(req.params.id);
+ const { name, email } = req.body;
+
+ const getRSVP = db.prepare(`SELECT * FROM rsvps WHERE (event_id = ${eventId} AND email = '${email}')`);
+ const insertRSVP = db.prepare(`INSERT INTO rsvps VALUES (@eventId, @name, @email)`);
+
+ let [rsvp] = getRSVP.all({ eventId, email });
+ if (rsvp) {
+ // This email has already RSVPed
+ res.status(200).json({ rsvp });
+ } else {
+ // New RSVP
+ insertRSVP.run({ name, email, eventId });
+ rsvp = getRSVP.run({ eventId, email });
+ res.status(201).json({ rsvp });
+ }
+});
+
+export default router;
diff --git a/backend/src/routes/users.js b/backend/src/routes/users.js
new file mode 100644
index 0000000..6d874e9
--- /dev/null
+++ b/backend/src/routes/users.js
@@ -0,0 +1,65 @@
+import { Router } from 'express';
+import db from '../db.js';
+
+const router = Router();
+
+export const getUser = (userId) => {
+ const byId = db.prepare('SELECT * FROM users WHERE id = @userId');
+ return byId.get({ userId });
+}
+
+router.get('/', (_req, res) => {
+ const listUsers = db.prepare(`SELECT * FROM users`)
+ const users = listUsers.all();
+ res.json(users);
+});
+
+router.post('/new', (req, res) => {
+ const data = req.body;
+ const cols = Object.keys(data).join(' , ');
+ const vals = Object.values(data).join(' , ');
+ const insertUser = db.prepare(`INSERT INTO users(@cols) VALUES (@vals)`);
+ const { lastInsertRowid: id } = insertUser.run({ cols, vals });
+ const user = getUser(id);
+ res.json(user);
+});
+
+router.get('/:id', (req, res) => {
+ const id = req.params.id;
+ const user = getUser(id);
+ if (!user) {
+ res.status(404).json({ error: 'User not found' });
+ }
+ res.json(user);
+});
+
+router.patch('/:id', (req, res) => {
+ const userId = req.params.id;
+ const patch = req.body;
+
+ const updateCol = db.prepare(`
+ UPDATE users SET @col = @val WHERE id = @userId
+ `);
+ const updateUser = db.transaction((patch) => {
+ for (const [col, val] of Object.entries(patch)) {
+ updateCol.run(col, val, userId);
+ };
+ });
+
+ updateUser(Object.entries(patch));
+ const updated = getUser(userId);
+ res.json(updated);
+});
+
+router.delete('/:id', (req, res) => {
+ const deleteUser = db.prepare(`DELETE FROM users WHERE id = @userId`)
+ const userId = parseInt(req.params.id);
+ const user = getUser(userId);
+ if (!user) {
+ res.status(404).json({ error: 'User not found' });
+ }
+ deleteUser.run({ userId });
+ res.json(user);
+});
+
+export default router;
diff --git a/backend/src/server.js b/backend/src/server.js
new file mode 100644
index 0000000..1861150
--- /dev/null
+++ b/backend/src/server.js
@@ -0,0 +1,40 @@
+import express from 'express';
+import cookieParser from 'cookie-parser';
+import logger from 'morgan';
+import cors from 'cors';
+import helmet from 'helmet';
+
+import apiRouter from './routes/api.js';
+
+
+const PORT = process.env.PORT || 3000;
+const NODE_ENV = process.env.NODE_ENV || 'development';
+
+const app = express();
+
+
+app.use(logger('dev'));
+app.use(express.json());
+app.use(express.urlencoded({ extended: false }));
+app.use(cookieParser());
+app.use(helmet());
+app.use(cors({
+ origin: 'http://localhost:5173'
+}));
+
+app.use('/api', apiRouter);
+
+app.use((_req, res) => {
+ res.status(404).json({
+ error: 'Not Found',
+ endpoints: [
+ '/api/events',
+ '/api/users'
+ ]
+ });
+});
+
+app.listen(PORT, () => {
+ console.log(`\nServer listening at http://localhost:${PORT}`);
+ console.log(`Server running in ${NODE_ENV} mode\n`);
+}) \ No newline at end of file