import type { IntegrationConnectionDefinition, IntegrationServiceDefinition, } from "@automate.ax/catalog" import { confirm, log, password, text } from "@clack/prompts" import { blue } from "ansis" import { z } from "zod" import { safelyPrompt } from "../utils" /** * Prints a provider-specific requirement before account connection. * * @param service - Service whose connection notice should be shown. */ export function printIntegrationConnectionNotice( service: IntegrationServiceDefinition, ) { const notice = service.connectionNotice if (!notice) return log.warn([notice.title, notice.description].join("\n")) log.message(blue.underline.link(notice.action.href, notice.action.label), { symbol: blue`↗`, }) } /** * Prompts for every field in a server-provided integration form. * * @param serviceName - Display name that identifies the credential provider. * @param connection - Form manifest whose fields should be collected. */ export async function promptIntegrationCredentials( serviceName: string, connection: Extract, ) { const data: Record = {} if (connection.credentialUrl) { log.message( blue.underline.link( connection.credentialUrl, `Create ${connection.name}`, ), { symbol: blue`↗` }, ) } for (const field of connection.fields) { const label = `${serviceName} ${field.label}` const message = field.description ? `${label} — ${field.description}` : label if (field.input === "boolean") { data[field.name] = await safelyPrompt( () => confirm({ initialValue: field.default, message, }), label, ) continue } const options = { message, placeholder: field.placeholder, validate: (value: string | undefined) => { if (field.required && !value) return `${label} is required.` if ( field.input === "number" && value && !Number.isFinite(Number(value)) ) { return `${label} must be a number.` } }, } const value = await safelyPrompt( () => field.input === "password" ? password(options) : text({ ...options, initialValue: field.default?.toString(), }), label, ) if (!value && !field.required) continue data[field.name] = field.input === "number" ? z.coerce.number().parse(value) : value } return data }