Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 72 additions & 0 deletions src/app/api/events/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import connectDB from "@/database/db";
import Event from "@/database/eventSchema";
import { NextRequest, NextResponse } from "next/server";
import mongoose from "mongoose";

export async function GET(request: NextRequest) {
try {
await connectDB();

const { searchParams } = new URL(request.url);
const anonUserId = searchParams.get("anonUserId");
const event = searchParams.get("event");
const sessionId = searchParams.get("sessionId");

const filter: Record<string, any> = {};

if (anonUserId) filter.anonUserId = anonUserId;
if (event) filter.event = event;
if (sessionId) {
if (!mongoose.Types.ObjectId.isValid(sessionId)) {
return NextResponse.json({ error: "Invalid sessionId" }, { status: 400 });
}
filter.sessionId = new mongoose.Types.ObjectId(sessionId);
}

const events = await Event.find(filter).sort({ ts: -1 });

return NextResponse.json(events);
} catch (error) {
console.error("GET /api/events error:", error);
return NextResponse.json({ error: "Failed to fetch events" }, { status: 500 });
}
}

export async function POST(request: NextRequest) {
try {
await connectDB();

const body = await request.json();
const { eventId, ts, anonUserId, sessionId, event, props } = body;

if (!eventId || !anonUserId || !sessionId || !event) {
return NextResponse.json(
{ error: "Missing required fields: eventId, anonUserId, sessionId, event" },
{ status: 400 },
);
}

if (!mongoose.Types.ObjectId.isValid(sessionId)) {
return NextResponse.json({ error: "Invalid sessionId" }, { status: 400 });
}
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice check for if the sessionid is valid! Can you also add a check for if the session exists? Something like this:

const sessionExists = await Session.exists({ _id: sessionId });
if (!sessionExists) {
return NextResponse.json({ error: "Session not found" }, { status: 404 });
}


const newEvent = new Event({
eventId,
ts: ts ? new Date(ts) : new Date(),
anonUserId,
sessionId: new mongoose.Types.ObjectId(sessionId),
event,
props: props ?? {},
});

const saved = await newEvent.save();

return NextResponse.json(saved, { status: 201 });
} catch (error: any) {
if (error.code === 11000) {
return NextResponse.json({ error: "an event with this eventId already exists" }, { status: 409 });
}
console.error("POST /api/events error:", error);
return NextResponse.json({ error: "failed to create an event" }, { status: 500 });
}
}
17 changes: 17 additions & 0 deletions src/database/eventSchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import mongoose, { Schema } from "mongoose";

const EventSchema = new Schema({
eventId: { type: String, required: true },
ts: { type: Date, required: true, default: Date.now },
anonUserId: { type: String, required: true },
sessionId: { type: Schema.Types.ObjectId, ref: "Session", required: true },
event: { type: String, required: true },
props: {
gameId: { type: String, default: null },
durationMs: { type: Number, default: null },
result: { type: String, default: null },
},
});

// uses the "events" collection in the testing database
export default mongoose.models.Event || mongoose.model("Event", EventSchema, "events");