import type { Encodable } from "@automate.ax/codec" import type { Vercel } from "@vercel/sdk" import * as z from "zod" import { defineAction } from "../../../automation/actions" import { getVercelApi, requireVercelTeamId, vercelAccessTokenAccountOptions, vercelAccountOptions, } from "../lib/api" import { VERCEL_TEAM_PAGE_SCHEMA, VERCEL_TEAM_SCHEMA, VERCEL_USER_RESPONSE_SCHEMA, vercelObjectSchema, } from "../lib/schemas" import { VERCEL_TEAM_READ_SCOPE, VERCEL_USER_READ_SCOPE } from "../lib/scopes" const VERCEL_TEAM_ROLE_SCHEMA = z.enum([ "BILLING", "CONTRIBUTOR", "DEVELOPER", "MEMBER", "OWNER", "SECURITY", "VIEWER", "VIEWER_FOR_PLUS", ]) const VERCEL_TEAM_MEMBERS_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( z.looseObject({ members: z .looseObject({ confirmed: z.boolean(), createdAt: z.number(), email: z.string(), role: VERCEL_TEAM_ROLE_SCHEMA, uid: z.string(), username: z.string(), }) .array(), pagination: z.looseObject({}), }), ) /** Gets the user represented by the connected Vercel account. */ export const getCurrentVercelUser = defineAction("Get current Vercel user") .describe("Gets the user represented by the connected Vercel account.") .account("vercel", vercelAccountOptions(VERCEL_USER_READ_SCOPE)) .output(VERCEL_USER_RESPONSE_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account }) => { const user = await getVercelApi(account).user.getAuthUser() if (!user) throw new Error("Vercel returned no authenticated user.") return user }) /** Lists teams visible to the connected Vercel user. */ export const listVercelTeams = defineAction("List Vercel teams") .describe("Lists a page of teams visible to the connected Vercel user.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Maximum number of teams to return. */ limit: z.number().int().min(1).max(100).prefault(20), /** Include teams created at or after this millisecond timestamp. */ since: z.number().int().nonnegative().optional(), /** Include teams created at or before this millisecond timestamp. */ until: z.number().int().nonnegative().optional(), }), ) .output(VERCEL_TEAM_PAGE_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).teams.getTeams(input), ) /** Lists members of one Vercel team. */ export const listVercelTeamMembers = defineAction("List Vercel team members") .describe("Lists a filtered page of members in one Vercel team.") .account("vercel", vercelAccountOptions(VERCEL_TEAM_READ_SCOPE)) .input( z.object({ /** Exclude members assigned to this project ID. */ excludeProjectId: z.string().min(1).optional(), /** Include members eligible for this project ID. */ eligibleForProjectId: z.string().min(1).optional(), /** Maximum members to return. */ limit: z.number().int().min(1).max(100).prefault(20), /** Filter by team role. */ role: VERCEL_TEAM_ROLE_SCHEMA.optional(), /** Search names, usernames, and email addresses. */ search: z.string().min(1).optional(), /** Include members added at or after this millisecond timestamp. */ since: z.number().int().nonnegative().optional(), /** Team ID. Defaults to the team selected during OAuth installation. */ teamId: z.string().min(1).optional(), /** Include members added at or before this millisecond timestamp. */ until: z.number().int().nonnegative().optional(), }), ) .output(VERCEL_TEAM_MEMBERS_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).teams.getTeamMembers({ limit: input.limit, teamId: requireVercelTeamId(account, input.teamId), ...(input.excludeProjectId && { excludeProject: input.excludeProjectId, }), ...(input.eligibleForProjectId && { eligibleMembersForProjectId: input.eligibleForProjectId, }), ...(input.role && { role: input.role }), ...(input.search && { search: input.search }), ...(input.since !== undefined && { since: input.since }), ...(input.until !== undefined && { until: input.until }), }), ) /** Gets one Vercel team by ID. */ export const getVercelTeam = defineAction("Get Vercel team") .describe( "Gets an explicit team or the team selected during OAuth installation.", ) .account("vercel", vercelAccountOptions(VERCEL_TEAM_READ_SCOPE)) .input( z.object({ /** Team ID. Defaults to the team selected during OAuth installation. */ teamId: z.string().min(1).optional(), }), ) .output(VERCEL_TEAM_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).teams.getTeam({ teamId: requireVercelTeamId(account, input.teamId), }), )