import { mutation, query } from "./_generated/server"; import { v } from "convex/values"; import { getAuthUserId } from "@convex-dev/auth/server"; export const listExisting = query({ args: { projectId: v.id("projects"), urls: v.array(v.string()), }, handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); if (!userId) return []; const project = await ctx.db.get(args.projectId); if (!project || project.userId !== userId) return []; const existing: string[] = []; for (const url of args.urls) { const match = await ctx.db .query("seenUrls") .withIndex("by_project_url", (q) => q.eq("projectId", args.projectId).eq("url", url) ) .first(); if (match) existing.push(url); } return existing; }, }); export const markSeenBatch = mutation({ args: { projectId: v.id("projects"), urls: v.array(v.string()), source: v.optional(v.string()), }, handler: async (ctx, args) => { const userId = await getAuthUserId(ctx); if (!userId) throw new Error("Unauthorized"); const project = await ctx.db.get(args.projectId); if (!project || project.userId !== userId) { throw new Error("Project not found or unauthorized"); } const now = Date.now(); for (const url of args.urls) { const existing = await ctx.db .query("seenUrls") .withIndex("by_project_url", (q) => q.eq("projectId", args.projectId).eq("url", url) ) .first(); if (existing) { await ctx.db.patch(existing._id, { lastSeenAt: now, source: args.source ?? existing.source, }); } else { await ctx.db.insert("seenUrls", { projectId: args.projectId, url, firstSeenAt: now, lastSeenAt: now, source: args.source, }); } } }, });