167 lines
4.0 KiB
TypeScript
167 lines
4.0 KiB
TypeScript
import { query, mutation } from "./_generated/server";
|
|
import { v } from "convex/values";
|
|
|
|
// List all non-DM channels
|
|
export const list = query({
|
|
args: {},
|
|
returns: v.array(
|
|
v.object({
|
|
_id: v.id("channels"),
|
|
_creationTime: v.number(),
|
|
name: v.string(),
|
|
type: v.string(),
|
|
})
|
|
),
|
|
handler: async (ctx) => {
|
|
const channels = await ctx.db.query("channels").collect();
|
|
return channels
|
|
.filter((c) => c.type !== "dm")
|
|
.sort((a, b) => a.name.localeCompare(b.name));
|
|
},
|
|
});
|
|
|
|
// Get single channel by ID
|
|
export const get = query({
|
|
args: { id: v.id("channels") },
|
|
returns: v.union(
|
|
v.object({
|
|
_id: v.id("channels"),
|
|
_creationTime: v.number(),
|
|
name: v.string(),
|
|
type: v.string(),
|
|
}),
|
|
v.null()
|
|
),
|
|
handler: async (ctx, args) => {
|
|
return await ctx.db.get(args.id);
|
|
},
|
|
});
|
|
|
|
// Create new channel
|
|
export const create = mutation({
|
|
args: {
|
|
name: v.string(),
|
|
type: v.optional(v.string()),
|
|
},
|
|
returns: v.object({ id: v.id("channels") }),
|
|
handler: async (ctx, args) => {
|
|
if (!args.name.trim()) {
|
|
throw new Error("Channel name required");
|
|
}
|
|
|
|
// Check for duplicate name
|
|
const existing = await ctx.db
|
|
.query("channels")
|
|
.withIndex("by_name", (q) => q.eq("name", args.name))
|
|
.unique();
|
|
|
|
if (existing) {
|
|
throw new Error("Channel already exists");
|
|
}
|
|
|
|
const id = await ctx.db.insert("channels", {
|
|
name: args.name,
|
|
type: args.type || "text",
|
|
});
|
|
|
|
return { id };
|
|
},
|
|
});
|
|
|
|
// Rename channel
|
|
export const rename = mutation({
|
|
args: {
|
|
id: v.id("channels"),
|
|
name: v.string(),
|
|
},
|
|
returns: v.object({
|
|
_id: v.id("channels"),
|
|
_creationTime: v.number(),
|
|
name: v.string(),
|
|
type: v.string(),
|
|
}),
|
|
handler: async (ctx, args) => {
|
|
if (!args.name.trim()) {
|
|
throw new Error("Name required");
|
|
}
|
|
|
|
const channel = await ctx.db.get(args.id);
|
|
if (!channel) {
|
|
throw new Error("Channel not found");
|
|
}
|
|
|
|
await ctx.db.patch(args.id, { name: args.name });
|
|
return { ...channel, name: args.name };
|
|
},
|
|
});
|
|
|
|
// Delete channel + cascade messages and keys
|
|
export const remove = mutation({
|
|
args: { id: v.id("channels") },
|
|
returns: v.object({ success: v.boolean() }),
|
|
handler: async (ctx, args) => {
|
|
const channel = await ctx.db.get(args.id);
|
|
if (!channel) {
|
|
throw new Error("Channel not found");
|
|
}
|
|
|
|
// Delete messages
|
|
const messages = await ctx.db
|
|
.query("messages")
|
|
.withIndex("by_channel", (q) => q.eq("channelId", args.id))
|
|
.collect();
|
|
for (const msg of messages) {
|
|
// Delete reactions for this message
|
|
const reactions = await ctx.db
|
|
.query("messageReactions")
|
|
.withIndex("by_message", (q) => q.eq("messageId", msg._id))
|
|
.collect();
|
|
for (const r of reactions) {
|
|
await ctx.db.delete(r._id);
|
|
}
|
|
await ctx.db.delete(msg._id);
|
|
}
|
|
|
|
// Delete channel keys
|
|
const keys = await ctx.db
|
|
.query("channelKeys")
|
|
.withIndex("by_channel", (q) => q.eq("channelId", args.id))
|
|
.collect();
|
|
for (const key of keys) {
|
|
await ctx.db.delete(key._id);
|
|
}
|
|
|
|
// Delete DM participants
|
|
const dmParts = await ctx.db
|
|
.query("dmParticipants")
|
|
.withIndex("by_channel", (q) => q.eq("channelId", args.id))
|
|
.collect();
|
|
for (const dp of dmParts) {
|
|
await ctx.db.delete(dp._id);
|
|
}
|
|
|
|
// Delete typing indicators
|
|
const typing = await ctx.db
|
|
.query("typingIndicators")
|
|
.withIndex("by_channel", (q) => q.eq("channelId", args.id))
|
|
.collect();
|
|
for (const t of typing) {
|
|
await ctx.db.delete(t._id);
|
|
}
|
|
|
|
// Delete voice states
|
|
const voiceStates = await ctx.db
|
|
.query("voiceStates")
|
|
.withIndex("by_channel", (q) => q.eq("channelId", args.id))
|
|
.collect();
|
|
for (const vs of voiceStates) {
|
|
await ctx.db.delete(vs._id);
|
|
}
|
|
|
|
// Delete channel itself
|
|
await ctx.db.delete(args.id);
|
|
|
|
return { success: true };
|
|
},
|
|
});
|