import { getAirtableApi } from "@automate.ax/integration-contracts/airtable" import * as z from "zod" import { defineAction } from "../../automation/actions" import { integrationScope as scope } from "../../automation/integrations" import { airtablePathSegment, airtablePersonalAccessTokenRequirement, } from "./lib" const AIRTABLE_CSV_SCHEMA = z .string() .min(1) .refine( (value) => new TextEncoder().encode(value).byteLength <= 2_000_000, "Airtable Sync CSV data must be at most 2 MB.", ) /** Sends CSV data to an existing Airtable Sync API table. */ export const syncAirtableCsvData = defineAction("Sync Airtable CSV data") .describe("Sends up to 2 MB of CSV data to an existing Sync API table.") .account( "airtable", airtablePersonalAccessTokenRequirement( scope.and("data.records:write", "schema.bases:write"), ), ) .input( z.object({ /** Stable Sync API endpoint ID from the table's sync settings. */ apiEndpointSyncId: z.string().trim().min(1), /** Stable Airtable base ID. */ baseId: z.string().trim().min(1), /** Raw CSV with at most 10,000 rows and 500 columns. */ csv: AIRTABLE_CSV_SCHEMA, /** Airtable table name or ID. */ table: z.string().trim().min(1), }), ) .output(z.undefined()) .retry({ replaySafety: "unsafe" }) .handler( async ({ account, input: { apiEndpointSyncId, baseId, csv, table } }) => { await getAirtableApi(account.secret).request( `${airtablePathSegment(baseId)}/${airtablePathSegment(table)}/sync/${airtablePathSegment(apiEndpointSyncId)}`, { body: csv, headers: { "Content-Type": "text/csv" }, method: "POST", }, ) }, )