import { ConvexError, v } from "convex/values"; import type { Doc, Id } from "./_generated/dataModel"; import { mutation, query } from "./_generated/server"; import { requireProjectMember } from "./authz"; const category = v.union( v.literal("required"), v.literal("integration"), v.literal("optional") ); const status = v.union( v.literal("missing"), v.literal("configured"), v.literal("invalid") ); const source = v.union( v.literal("detected"), v.literal("user"), v.literal("system") ); export const list = query({ args: { projectId: v.id("projects") }, handler: async ( ctx, args ): Promise[]> => { const { organizationId } = await requireProjectMember(ctx, args.projectId); return await ctx.db .query("projectEnvironmentVariables") .withIndex("by_projectId", (q) => q.eq("projectId", args.projectId)) .filter((q) => q.eq(q.field("organizationId"), organizationId)) .order("asc") .collect(); }, }); export const upsert = mutation({ args: { category, description: v.optional(v.string()), name: v.string(), projectId: v.id("projects"), secretReference: v.optional(v.string()), source, status, }, handler: async (ctx, args): Promise> => { const { organizationId } = await requireProjectMember(ctx, args.projectId); const name = args.name.trim(); if (!name) { throw new ConvexError("Environment variable name is required"); } const existing = await ctx.db .query("projectEnvironmentVariables") .withIndex("by_projectId_and_name", (q) => q.eq("projectId", args.projectId).eq("name", name) ) .unique(); const value = { category: args.category, description: args.description, name, organizationId, projectId: args.projectId, secretReference: args.secretReference, source: args.source, status: args.status, updatedAt: Date.now(), }; const id: Id<"projectEnvironmentVariables"> = existing ? existing._id : await ctx.db.insert("projectEnvironmentVariables", value); if (existing) { await ctx.db.patch(id, value); } const saved = await ctx.db.get(id); if (!saved) { throw new ConvexError("Environment variable could not be saved"); } return saved; }, });