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, vercelAccessTokenAccountOptions } from "../lib/api" import { vercelObjectSchema } from "../lib/schemas" const VERCEL_ALIAS_SCHEMA = vercelObjectSchema< Awaited> & Encodable >(z.looseObject({ alias: z.string() })) const VERCEL_ALIASES_SCHEMA = vercelObjectSchema< Awaited> & Encodable >( z.looseObject({ aliases: z.looseObject({ alias: z.string() }).array(), pagination: z.looseObject({}), }), ) const ASSIGNED_VERCEL_ALIAS_SCHEMA = vercelObjectSchema< Awaited> & Encodable >(z.looseObject({ alias: z.string(), uid: z.string() })) const DELETED_VERCEL_ALIAS_SCHEMA = vercelObjectSchema< Awaited> & Encodable >(z.looseObject({ status: z.literal("SUCCESS") })) /** Lists aliases in a Vercel account or team. */ export const listVercelAliases = defineAction("List Vercel aliases") .describe("Lists a filtered page of deployment aliases.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Filter by one or more domain names. */ domains: z.string().min(1).array().optional(), /** Continuation timestamp from a previous page. */ from: z.number().int().nonnegative().optional(), /** Maximum aliases to return. */ limit: z.number().int().min(1).max(100).prefault(20), /** Filter by project ID. */ projectId: z.string().min(1).optional(), /** Show aliases that would be affected by rolling back this deployment. */ rollbackDeploymentId: z.string().min(1).optional(), /** Include aliases created at or after this millisecond timestamp. */ since: z.number().int().nonnegative().optional(), /** Team ID for team-owned aliases. */ teamId: z.string().min(1).optional(), /** Include aliases created at or before this millisecond timestamp. */ until: z.number().int().nonnegative().optional(), }), ) .output(VERCEL_ALIASES_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).aliases.listAliases({ limit: input.limit, ...(input.domains && { domain: input.domains }), ...(input.from !== undefined && { from: input.from }), ...(input.projectId && { projectId: input.projectId }), ...(input.rollbackDeploymentId && { rollbackDeploymentId: input.rollbackDeploymentId, }), ...(input.since !== undefined && { since: input.since }), ...(input.teamId && { teamId: input.teamId }), ...(input.until !== undefined && { until: input.until }), }), ) /** Gets one Vercel deployment alias. */ export const getVercelAlias = defineAction("Get Vercel alias") .describe("Gets one deployment alias by hostname or ID.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Alias hostname or ID. */ alias: z.string().min(1), /** Require the alias to belong to this project ID. */ projectId: z.string().min(1).optional(), /** Team ID for a team-owned alias. */ teamId: z.string().min(1).optional(), }), ) .output(VERCEL_ALIAS_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => getVercelApi(account).aliases.getAlias({ idOrAlias: input.alias, ...(input.projectId && { projectId: input.projectId }), ...(input.teamId && { teamId: input.teamId }), }), ) /** Assigns a Vercel alias to a deployment or redirect. */ export const assignVercelAlias = defineAction("Assign Vercel alias") .describe("Assigns an alias to a deployment or creates an alias redirect.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z .object({ /** Alias hostname. */ alias: z.string().min(1), /** Deployment or existing alias ID or URL. */ deployment: z.string().min(1), /** Redirect destination instead of the deployment. */ redirect: z.string().min(1).nullable().optional(), /** Team ID for a team-owned deployment. */ teamId: z.string().min(1).optional(), }) .refine((input) => !input.redirect || input.redirect !== input.alias, { message: "An alias cannot redirect to itself.", path: ["redirect"], }), ) .output(ASSIGNED_VERCEL_ALIAS_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).aliases.assignAlias({ id: input.deployment, requestBody: { alias: input.alias, ...(input.redirect !== undefined && { redirect: input.redirect }), }, ...(input.teamId && { teamId: input.teamId }), }), ) /** Deletes one Vercel deployment alias. */ export const deleteVercelAlias = defineAction("Delete Vercel alias") .describe("Deletes one deployment alias by hostname or ID.") .account("vercel", vercelAccessTokenAccountOptions()) .input( z.object({ /** Alias hostname or ID. */ alias: z.string().min(1), /** Team ID for a team-owned alias. */ teamId: z.string().min(1).optional(), }), ) .output(DELETED_VERCEL_ALIAS_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => getVercelApi(account).aliases.deleteAlias({ aliasId: input.alias, ...(input.teamId && { teamId: input.teamId }), }), )