All files / convex/mutations/dashboard/discord/guildSupportConfigs update.ts

100% Statements 95/95
100% Branches 17/17
100% Functions 3/3
100% Lines 95/95

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 961x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 13x 13x 13x 13x 13x 13x 13x 13x 1x 1x 1x 1x 1x 13x 13x 13x 13x 11x 11x 11x 11x 13x 1x 1x 1x 4x 4x 4x 4x 3x 2x 4x 3x 3x 3x 3x 3x 4x 4x 4x 1x 1x 4x 4x 4x 4x 4x 2x 2x 2x 4x 1x 1x 1x 1x 1x 1x 1x 4x  
import { isDiscordSnowflake } from "@workspace/shared/discordRuntimeConfig"
import { ConvexError, v } from "convex/values"
 
import { mutation } from "../../../../_generated/server"
import {
  guildSupportEscalationPolicy,
  guildSupportTargetType,
  guildSupportTranscriptPolicy,
} from "../../../../dbTables/guildSupportConfigs"
import { requireDiscordGuildManager } from "../../../../lib/auth"
 
const MAX_STAFF_ROLES = 20
 
const guildSupportConfigResult = v.object({
  supportConfigId: v.id("guildSupportConfigs"),
  enabled: v.boolean(),
  staffRoleIds: v.array(v.string()),
  targetId: v.optional(v.string()),
  targetType: guildSupportTargetType,
  transcriptPolicy: guildSupportTranscriptPolicy,
  escalationPolicy: guildSupportEscalationPolicy,
  updatedAt: v.number(),
})
 
export const update = mutation({
  args: {
    discordGuildId: v.string(),
    enabled: v.boolean(),
    staffRoleIds: v.array(v.string()),
    targetId: v.optional(v.union(v.string(), v.null())),
    targetType: guildSupportTargetType,
    transcriptPolicy: guildSupportTranscriptPolicy,
    escalationPolicy: guildSupportEscalationPolicy,
  },
  returns: guildSupportConfigResult,
  handler: async (ctx, args) => {
    const guild = await ctx.db
      .query("guilds")
      .withIndex("by_discord_guild_id", (q) =>
        q.eq("discordGuildId", args.discordGuildId)
      )
      .unique()
 
    if (!guild) {
      throw new ConvexError({
        code: "GUILD_NOT_FOUND",
        message: "Discord server was not found.",
      })
    }
 
    await requireDiscordGuildManager(ctx, guild._id)
 
    throw new ConvexError({
      code: "SUPPORT_CONFIGURATION_DISABLED",
      message:
        "Guild support configuration is temporarily disabled while support tickets are being rebuilt and tested.",
    })
  },
})
 
export function normalizeSupportStaffRoleIds(values: string[]): string[] {
  const normalized = values.map((value) => value.trim()).filter(Boolean)
 
  if (
    normalized.length > MAX_STAFF_ROLES ||
    normalized.some((value) => !isDiscordSnowflake(value)) ||
    new Set(normalized).size !== normalized.length
  ) {
    throw new ConvexError({
      code: "INVALID_SUPPORT_STAFF_ROLES",
      message: `Support staff roles must contain at most ${MAX_STAFF_ROLES} unique Discord role IDs.`,
    })
  }
 
  return normalized
}
 
export function normalizeSupportTargetId(
  value: string | null | undefined
): string | undefined {
  const normalized = value?.trim()
 
  if (!normalized) {
    return undefined
  }
 
  if (!isDiscordSnowflake(normalized)) {
    throw new ConvexError({
      code: "INVALID_SUPPORT_TARGET",
      message: "The support destination must be a valid Discord ID.",
    })
  }
 
  return normalized
}