import type { Encodable } from "@automate.ax/codec" import type { Vercel } from "@vercel/sdk" import * as z from "zod" import { defineAction } from "../../../automation/actions" import { defineScopedVercelSdkAction } from "../lib/action" import { getVercelAccessToken, getVercelTeamId, vercelAccountOptions, } from "../lib/api" import { VERCEL_GLOBAL_CONFIGS_SCHEMA, vercelObjectSchema, } from "../lib/schemas" import { VERCEL_EDGE_CONFIG_READ_SCOPE, VERCEL_EDGE_CONFIG_WRITE_SCOPE, } from "../lib/scopes" type GlobalConfig = Vercel["globalConfig"] const VERCEL_GLOBAL_CONFIG_MUTATION_RESULT_SCHEMA = vercelObjectSchema< Record >(z.looseObject({})) /** Lists Vercel Global Config stores. */ export const listVercelGlobalConfigs = defineAction( "List Vercel Global Configs", ) .describe("Lists Global Config stores in the selected account or team.") .account("vercel", vercelAccountOptions(VERCEL_EDGE_CONFIG_READ_SCOPE)) .input( z.object({ slug: z.string().min(1).optional(), teamId: z.string().min(1).optional(), }), ) .output(VERCEL_GLOBAL_CONFIGS_SCHEMA) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => { const url = new URL("https://api.vercel.com/v1/global-config") const teamId = getVercelTeamId(account, input.teamId) if (input.slug) url.searchParams.set("slug", input.slug) if (teamId) url.searchParams.set("teamId", teamId) const response = await fetch(url, { headers: { authorization: `Bearer ${getVercelAccessToken(account)}`, }, }) if (!response.ok) { throw new Error( `Vercel Global Config listing failed with HTTP ${response.status}.`, ) } return VERCEL_GLOBAL_CONFIGS_SCHEMA.parse(await response.json()) }) /** Gets one Vercel Global Config store. */ export const getVercelGlobalConfig = defineScopedVercelSdkAction({ description: "Gets metadata for one Global Config store.", handler: (api, request: Parameters[0]) => api.globalConfig.getEdgeConfig(request), name: "Get Vercel Global Config", replaySafety: "safe", scope: VERCEL_EDGE_CONFIG_READ_SCOPE, }) /** Creates a Vercel Global Config store. */ export const createVercelGlobalConfig = defineScopedVercelSdkAction({ description: "Creates a Global Config store with optional initial items.", handler: (api, request: Parameters[0]) => api.globalConfig.createEdgeConfig(request), name: "Create Vercel Global Config", replaySafety: "unsafe", scope: VERCEL_EDGE_CONFIG_WRITE_SCOPE, }) /** Updates one Vercel Global Config store. */ export const updateVercelGlobalConfig = defineScopedVercelSdkAction({ description: "Renames or transfers one Global Config store.", handler: (api, request: Parameters[0]) => api.globalConfig.updateEdgeConfig(request), name: "Update Vercel Global Config", replaySafety: "unsafe", scope: VERCEL_EDGE_CONFIG_WRITE_SCOPE, }) /** Deletes one Vercel Global Config store. */ export const deleteVercelGlobalConfig = defineScopedVercelSdkAction({ description: "Permanently deletes one Global Config store.", handler: (api, request: Parameters[0]) => api.globalConfig.deleteEdgeConfig(request), name: "Delete Vercel Global Config", replaySafety: "unsafe", scope: VERCEL_EDGE_CONFIG_WRITE_SCOPE, }) /** Lists every item in one Vercel Global Config store. */ export const listVercelGlobalConfigItems = defineScopedVercelSdkAction({ description: "Lists the key-value items stored in one Global Config.", handler: (api, request: Parameters[0]) => api.globalConfig.getEdgeConfigItems(request), name: "List Vercel Global Config items", replaySafety: "safe", scope: VERCEL_EDGE_CONFIG_READ_SCOPE, }) /** Gets one item from a Vercel Global Config store. */ export const getVercelGlobalConfigItem = defineScopedVercelSdkAction({ description: "Gets one Global Config item by key.", handler: (api, request: Parameters[0]) => api.globalConfig.getEdgeConfigItem(request), name: "Get Vercel Global Config item", replaySafety: "safe", scope: VERCEL_EDGE_CONFIG_READ_SCOPE, }) /** Applies item mutations to one Vercel Global Config store. */ export const updateVercelGlobalConfigItems = defineAction( "Update Vercel Global Config items", ) .describe("Creates, updates, or deletes items in one Global Config.") .account("vercel", vercelAccountOptions(VERCEL_EDGE_CONFIG_WRITE_SCOPE)) .input( z.object({ /** Global Config ID. */ edgeConfigId: z.string().min(1), /** Item mutations applied atomically by Vercel. */ items: z .discriminatedUnion("operation", [ z.object({ key: z.string().min(1), operation: z.enum(["create", "update", "upsert"]), value: z.json(), }), z.object({ key: z.string().min(1), operation: z.literal("delete"), }), ]) .array() .min(1), /** Team ID. OAuth accounts default to the installed team. */ teamId: z.string().min(1).optional(), }), ) .output(VERCEL_GLOBAL_CONFIG_MUTATION_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { const teamId = getVercelTeamId(account, input.teamId) const response = await fetch( `https://api.vercel.com/v1/edge-config/${encodeURIComponent(input.edgeConfigId)}/items${teamId ? `?teamId=${encodeURIComponent(teamId)}` : ""}`, { body: JSON.stringify({ items: input.items }), headers: { authorization: `Bearer ${getVercelAccessToken(account)}`, "content-type": "application/json", }, method: "PATCH", }, ) if (!response.ok) { throw new Error( `Vercel Global Config item update failed with HTTP ${response.status}.`, ) } return VERCEL_GLOBAL_CONFIG_MUTATION_RESULT_SCHEMA.parse( await response.json(), ) }) /** Lists masked access tokens for one Vercel Global Config store. */ export const listVercelGlobalConfigTokens = defineScopedVercelSdkAction({ description: "Lists masked tokens for one Global Config.", handler: (api, request: Parameters[0]) => api.globalConfig.getEdgeConfigTokens(request), name: "List Vercel Global Config tokens", replaySafety: "safe", scope: VERCEL_EDGE_CONFIG_READ_SCOPE, }) /** Creates an access token for one Vercel Global Config store. */ export const createVercelGlobalConfigToken = defineScopedVercelSdkAction({ description: "Creates a token and returns its secret once.", handler: ( api, request: Parameters[0], ) => api.globalConfig.createEdgeConfigToken(request), name: "Create Vercel Global Config token", replaySafety: "unsafe", scope: VERCEL_EDGE_CONFIG_WRITE_SCOPE, }) /** Deletes one or more Vercel Global Config tokens. */ export const deleteVercelGlobalConfigTokens = defineScopedVercelSdkAction({ description: "Deletes selected tokens from one Global Config.", handler: ( api, request: Parameters[0], ) => api.globalConfig.deleteEdgeConfigTokens(request), name: "Delete Vercel Global Config tokens", replaySafety: "unsafe", scope: VERCEL_EDGE_CONFIG_WRITE_SCOPE, })