import * as z from "zod" import { defineAction } from "../../../automation/actions" import { getGoogleSheetsApi, normalizeSpreadsheetId, normalizeValueUpdate, toGoogleDateTimeRender, toGoogleMajorDimension, toGoogleValueRender, } from "../lib/google-sheets" import { GOOGLE_SHEETS_WRITE_REQUIREMENT } from "../lib/scopes" import { BATCH_VALUE_UPDATE_SCHEMA, CELL_VALUES_SCHEMA, DATE_TIME_RENDER_SCHEMA, MAJOR_DIMENSION_SCHEMA, SPREADSHEET_REFERENCE_SCHEMA, VALUE_INPUT_MODE_SCHEMA, VALUE_RENDER_SCHEMA, } from "../lib/schemas" const VALUE_UPDATE_INPUT_SCHEMA = z.object({ /** Whether the outer array represents rows or columns. */ majorDimension: MAJOR_DIMENSION_SCHEMA.optional(), /** A1 range or named range receiving the values. */ range: z.string().min(1), /** Cell values. Null clears the corresponding cell. */ values: CELL_VALUES_SCHEMA, }) /** Writes one or more value ranges atomically. */ export const writeGoogleSheetsValues = defineAction( "Write Google Sheets values", ) .describe("Writes one or more matrices and returns complete update counts.") .account("google", GOOGLE_SHEETS_WRITE_REQUIREMENT) .input( z.object({ /** Whether updated values should be included in the result. */ includeValues: z.boolean().optional(), /** Whether strings are parsed like UI input or stored literally. */ inputMode: VALUE_INPUT_MODE_SCHEMA.optional(), /** Date and time representation in returned values. */ responseDateTimeRender: DATE_TIME_RENDER_SCHEMA.optional(), /** Representation used for returned values. */ responseValueRender: VALUE_RENDER_SCHEMA.optional(), /** Spreadsheet ID or standard Google Sheets URL. */ spreadsheet: SPREADSHEET_REFERENCE_SCHEMA, /** One or more range updates performed atomically. */ updates: z.union([ VALUE_UPDATE_INPUT_SCHEMA, VALUE_UPDATE_INPUT_SCHEMA.array().min(1), ]), }), ) .output(BATCH_VALUE_UPDATE_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { const { data } = await getGoogleSheetsApi( account.secret, ).spreadsheets.values.batchUpdate({ requestBody: { data: (Array.isArray(input.updates) ? input.updates : [input.updates] ).map((update) => ({ majorDimension: toGoogleMajorDimension(update.majorDimension), range: update.range, values: update.values.map((row) => row.map((value) => value ?? "")), })), includeValuesInResponse: input.includeValues ?? false, responseDateTimeRenderOption: toGoogleDateTimeRender( input.responseDateTimeRender, ), responseValueRenderOption: toGoogleValueRender( input.responseValueRender, ), valueInputOption: input.inputMode === "raw" ? "RAW" : "USER_ENTERED", }, spreadsheetId: normalizeSpreadsheetId(input.spreadsheet), }) return { spreadsheetId: data.spreadsheetId ?? "", totalUpdatedCells: data.totalUpdatedCells ?? 0, totalUpdatedColumns: data.totalUpdatedColumns ?? 0, totalUpdatedRows: data.totalUpdatedRows ?? 0, totalUpdatedSheets: data.totalUpdatedSheets ?? 0, updates: (data.responses ?? []).map(normalizeValueUpdate), } })