Files
lemonspace_app/convex/canvases.ts

143 lines
3.8 KiB
TypeScript

import { query, mutation } from "./_generated/server";
import { v } from "convex/values";
import { optionalAuth, requireAuth } from "./helpers";
// ============================================================================
// Queries
// ============================================================================
/**
* Alle Canvases des eingeloggten Users, sortiert nach letzter Bearbeitung.
*/
export const list = query({
args: {},
handler: async (ctx) => {
const user = await requireAuth(ctx);
return await ctx.db
.query("canvases")
.withIndex("by_owner_updated", (q) => q.eq("ownerId", user.userId))
.order("desc")
.collect();
},
});
/**
* Einzelnen Canvas laden — mit Owner-Check.
*/
export const get = query({
args: { canvasId: v.id("canvases") },
handler: async (ctx, { canvasId }) => {
const user = await optionalAuth(ctx);
if (!user) {
return null;
}
const canvas = await ctx.db.get(canvasId);
if (!canvas || canvas.ownerId !== user.userId) {
return null;
}
return canvas;
},
});
// ============================================================================
// Mutations
// ============================================================================
/**
* Neuen Canvas erstellen.
*/
export const create = mutation({
args: {
name: v.string(),
description: v.optional(v.string()),
},
handler: async (ctx, { name, description }) => {
const user = await requireAuth(ctx);
const now = Date.now();
const canvasId = await ctx.db.insert("canvases", {
name,
ownerId: user.userId,
description,
updatedAt: now,
});
return canvasId;
},
});
/**
* Canvas umbenennen oder Beschreibung ändern.
*/
export const update = mutation({
args: {
canvasId: v.id("canvases"),
name: v.optional(v.string()),
description: v.optional(v.string()),
},
handler: async (ctx, { canvasId, name, description }) => {
const user = await requireAuth(ctx);
const canvas = await ctx.db.get(canvasId);
if (!canvas || canvas.ownerId !== user.userId) {
throw new Error("Canvas not found");
}
const updates: Record<string, unknown> = { updatedAt: Date.now() };
if (name !== undefined) updates.name = name;
if (description !== undefined) updates.description = description;
await ctx.db.patch(canvasId, updates);
},
});
/**
* Canvas löschen — entfernt auch alle zugehörigen Nodes und Edges.
*/
export const remove = mutation({
args: { canvasId: v.id("canvases") },
handler: async (ctx, { canvasId }) => {
const user = await requireAuth(ctx);
const canvas = await ctx.db.get(canvasId);
if (!canvas || canvas.ownerId !== user.userId) {
throw new Error("Canvas not found");
}
// Alle Nodes dieses Canvas löschen
const nodes = await ctx.db
.query("nodes")
.withIndex("by_canvas", (q) => q.eq("canvasId", canvasId))
.collect();
for (const node of nodes) {
await ctx.db.delete(node._id);
}
// Alle Edges dieses Canvas löschen
const edges = await ctx.db
.query("edges")
.withIndex("by_canvas", (q) => q.eq("canvasId", canvasId))
.collect();
for (const edge of edges) {
await ctx.db.delete(edge._id);
}
// Canvas selbst löschen
await ctx.db.delete(canvasId);
},
});
/**
* Canvas-Thumbnail aktualisieren.
*/
export const setThumbnail = mutation({
args: {
canvasId: v.id("canvases"),
thumbnail: v.id("_storage"),
},
handler: async (ctx, { canvasId, thumbnail }) => {
const user = await requireAuth(ctx);
const canvas = await ctx.db.get(canvasId);
if (!canvas || canvas.ownerId !== user.userId) {
throw new Error("Canvas not found");
}
await ctx.db.patch(canvasId, { thumbnail, updatedAt: Date.now() });
},
});