This commit is contained in:
2026-02-04 01:05:00 +00:00
parent f9222627ef
commit d02d95e680
30 changed files with 2449 additions and 326 deletions

View File

@@ -83,6 +83,97 @@ export const updateProject = mutation({
},
});
export const deleteProject = mutation({
args: { projectId: v.id("projects") },
handler: async (ctx, args) => {
const userId = await getAuthUserId(ctx);
if (!userId) throw new Error("Unauthorized");
const projects = await ctx.db
.query("projects")
.withIndex("by_owner", (q) => q.eq("userId", userId))
.collect();
if (projects.length <= 1) {
throw new Error("You must keep at least one project.");
}
const project = projects.find((item) => item._id === args.projectId);
if (!project || project.userId !== userId) {
throw new Error("Project not found or unauthorized");
}
const remainingProjects = projects.filter((item) => item._id !== args.projectId);
let newDefaultId: typeof args.projectId | null = null;
const remainingDefault = remainingProjects.find((item) => item.isDefault);
if (project.isDefault) {
newDefaultId = remainingProjects[0]?._id ?? null;
} else if (!remainingDefault) {
newDefaultId = remainingProjects[0]?._id ?? null;
}
if (newDefaultId) {
await ctx.db.patch(newDefaultId, { isDefault: true });
}
const dataSources = await ctx.db
.query("dataSources")
.filter((q) => q.eq(q.field("projectId"), args.projectId))
.collect();
for (const source of dataSources) {
await ctx.db.delete(source._id);
}
const analyses = await ctx.db
.query("analyses")
.withIndex("by_project_createdAt", (q) => q.eq("projectId", args.projectId))
.collect();
for (const analysis of analyses) {
await ctx.db.delete(analysis._id);
}
const analysisJobs = await ctx.db
.query("analysisJobs")
.withIndex("by_project_createdAt", (q) => q.eq("projectId", args.projectId))
.collect();
for (const job of analysisJobs) {
await ctx.db.delete(job._id);
}
const searchJobs = await ctx.db
.query("searchJobs")
.withIndex("by_project_createdAt", (q) => q.eq("projectId", args.projectId))
.collect();
for (const job of searchJobs) {
await ctx.db.delete(job._id);
}
const opportunities = await ctx.db
.query("opportunities")
.withIndex("by_project_createdAt", (q) => q.eq("projectId", args.projectId))
.collect();
for (const opportunity of opportunities) {
await ctx.db.delete(opportunity._id);
}
const seenUrls = await ctx.db
.query("seenUrls")
.withIndex("by_project_lastSeen", (q) => q.eq("projectId", args.projectId))
.collect();
for (const seen of seenUrls) {
await ctx.db.delete(seen._id);
}
await ctx.db.delete(args.projectId);
return {
deletedProjectId: args.projectId,
newDefaultProjectId: newDefaultId ?? remainingDefault?._id ?? remainingProjects[0]?._id ?? null,
};
},
});
export const toggleDataSourceConfig = mutation({
args: { projectId: v.id("projects"), sourceId: v.id("dataSources"), selected: v.boolean() },
handler: async (ctx, args) => {