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, } from "../lib/api" import { vercelObjectSchema } from "../lib/schemas" const VERCEL_SHARED_ENVIRONMENT_TARGET_SCHEMA = z.enum([ "development", "preview", "production", ]) const VERCEL_SHARED_ENVIRONMENT_VARIABLE_TYPE_SCHEMA = z.enum([ "encrypted", "sensitive", ]) const VERCEL_SHARED_ENVIRONMENT_VARIABLE_MUTATION_SCHEMA = z.looseObject({ failed: z .looseObject({ error: z.looseObject({ message: z.string() }) }) .array(), }) const VERCEL_CREATED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( VERCEL_SHARED_ENVIRONMENT_VARIABLE_MUTATION_SCHEMA.extend({ created: z.array(z.looseObject({})), }), ) const VERCEL_UPDATED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( VERCEL_SHARED_ENVIRONMENT_VARIABLE_MUTATION_SCHEMA.extend({ updated: z.array(z.looseObject({})), }), ) const VERCEL_DELETED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( VERCEL_SHARED_ENVIRONMENT_VARIABLE_MUTATION_SCHEMA.extend({ deleted: z.string().array(), }), ) const VERCEL_SHARED_ENVIRONMENT_VARIABLES_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( z.looseObject({ data: z.looseObject({}).array(), pagination: z.looseObject({}), }), ) const VERCEL_UNLINKED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA = vercelObjectSchema< Awaited> & Encodable >(z.looseObject({ id: z.string() })) /** Creates one shared Vercel environment variable. */ export const createVercelSharedEnvironmentVariable = defineAction( "Create Vercel shared environment variable", ) .describe("Creates one environment variable shared by a Vercel team.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Human-readable context for the variable. */ comment: z.string().optional(), /** Environment variable name. */ key: z.string().min(1), /** Standard deployment targets. */ targets: VERCEL_SHARED_ENVIRONMENT_TARGET_SCHEMA.array().prefault([ "production", "preview", "development", ]), /** Team ID. */ teamId: z.string().min(1), /** Storage type. */ type: VERCEL_SHARED_ENVIRONMENT_VARIABLE_TYPE_SCHEMA.prefault( "encrypted", ), /** Environment variable value. */ value: z.string(), }), ) .output(VERCEL_CREATED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).environment.createSharedEnvVariable({ requestBody: { evs: [ { key: input.key, value: input.value, ...(input.comment !== undefined && { comment: input.comment }), }, ], target: input.targets, type: input.type, }, teamId: requireVercelTeamId(account, input.teamId), }), ) /** Lists shared Vercel environment variables without decrypting values. */ export const listVercelSharedEnvironmentVariables = defineAction( "List Vercel shared environment variables", ) .describe("Lists shared environment-variable metadata for a Vercel team.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Exclude these shared variable IDs. */ excludeIds: z.string().min(1).array().optional(), /** Include only these shared variable IDs. */ ids: z.string().min(1).array().optional(), /** Filter by linked project ID. */ projectId: z.string().min(1).optional(), /** Search variable names. */ search: z.string().min(1).optional(), /** Team ID. */ teamId: z.string().min(1), }), ) .output(VERCEL_SHARED_ENVIRONMENT_VARIABLES_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).environment.listSharedEnvVariable({ teamId: requireVercelTeamId(account, input.teamId), ...(input.excludeIds && { excludeIdsQueryParameter: input.excludeIds.join(","), }), ...(input.ids && { ids: input.ids.join(",") }), ...(input.projectId && { projectId: input.projectId }), ...(input.search && { search: input.search }), }), ) /** Updates one shared Vercel environment variable. */ export const updateVercelSharedEnvironmentVariable = defineAction( "Update Vercel shared environment variable", ) .describe("Updates one shared environment variable and its project links.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Replacement human-readable context. */ comment: z.string().optional(), /** Shared environment variable ID. */ environmentVariableId: z.string().min(1), /** Replacement variable name. */ key: z.string().min(1).optional(), /** Project IDs to link. */ linkProjectIds: z.string().min(1).array().optional(), /** Replacement deployment targets. */ targets: VERCEL_SHARED_ENVIRONMENT_TARGET_SCHEMA.array().optional(), /** Team ID. */ teamId: z.string().min(1), /** Replacement storage type. */ type: VERCEL_SHARED_ENVIRONMENT_VARIABLE_TYPE_SCHEMA.optional(), /** Project IDs to unlink. */ unlinkProjectIds: z.string().min(1).array().optional(), /** Replacement value. */ value: z.string().optional(), }), ) .output(VERCEL_UPDATED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).environment.updateSharedEnvVariable({ requestBody: { updates: { [input.environmentVariableId]: { ...(input.comment !== undefined && { comment: input.comment }), ...(input.key && { key: input.key }), ...(input.targets && { target: input.targets }), ...(input.type && { type: input.type }), ...(input.value !== undefined && { value: input.value }), ...((input.linkProjectIds || input.unlinkProjectIds) && { projectIdUpdates: { ...(input.linkProjectIds && { link: input.linkProjectIds }), ...(input.unlinkProjectIds && { unlink: input.unlinkProjectIds, }), }, }), }, }, }, teamId: requireVercelTeamId(account, input.teamId), }), ) /** Deletes shared Vercel environment variables. */ export const deleteVercelSharedEnvironmentVariables = defineAction( "Delete Vercel shared environment variables", ) .describe("Deletes one or more shared environment variables.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Shared environment variable IDs. */ environmentVariableIds: z.string().min(1).array().min(1), /** Team ID. */ teamId: z.string().min(1), }), ) .output(VERCEL_DELETED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).environment.deleteSharedEnvVariable({ requestBody: { ids: input.environmentVariableIds }, teamId: requireVercelTeamId(account, input.teamId), }), ) /** Disconnects a shared Vercel environment variable from one project. */ export const disconnectVercelSharedEnvironmentVariable = defineAction( "Disconnect Vercel shared environment variable", ) .describe("Disconnects one shared environment variable from one project.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Shared environment variable ID. */ environmentVariableId: z.string().min(1), /** Project ID. */ projectId: z.string().min(1), /** Team ID. */ teamId: z.string().min(1), }), ) .output(VERCEL_UNLINKED_SHARED_ENVIRONMENT_VARIABLE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).environment.unlinkSharedEnvVariable({ id: input.environmentVariableId, projectId: input.projectId, teamId: requireVercelTeamId(account, input.teamId), }), )