import * as z from "zod" import { defineAction } from "../../../automation/actions" import { assertSourceRowNumbers, createConsecutiveRowRanges, getGoogleSheetsApi, normalizeSpreadsheetId, resolveRowSource, } from "../lib/google-sheets" import { GOOGLE_SHEETS_WRITE_REQUIREMENT } from "../lib/scopes" import { ROW_MUTATION_RESULT_SCHEMA, ROW_SOURCE_SCHEMA, SPREADSHEET_REFERENCE_SCHEMA, } from "../lib/schemas" /** Deletes explicitly numbered rows, grouping adjacent rows into requests. */ export const deleteGoogleSheetsRows = defineAction("Delete Google Sheets rows") .describe("Deletes one or more data rows without shifting the wrong targets.") .account("google", GOOGLE_SHEETS_WRITE_REQUIREMENT) .input( z.object({ /** One or more one-based row numbers. */ rowNumbers: z.union([ z.number().int().positive(), z.number().int().positive().array().min(1).max(1000), ]), /** Header-backed sheet or native table. */ source: ROW_SOURCE_SCHEMA, /** Spreadsheet ID or standard Google Sheets URL. */ spreadsheet: SPREADSHEET_REFERENCE_SCHEMA, }), ) .output(ROW_MUTATION_RESULT_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { const sheetsApi = getGoogleSheetsApi(account.secret) const spreadsheetId = normalizeSpreadsheetId(input.spreadsheet) const source = await resolveRowSource( sheetsApi, spreadsheetId, input.source, ) const rowNumbers = [ ...new Set( Array.isArray(input.rowNumbers) ? input.rowNumbers : [input.rowNumbers], ), ].toSorted((left, right) => left - right) assertSourceRowNumbers(source, rowNumbers) await sheetsApi.spreadsheets.batchUpdate({ requestBody: { requests: createConsecutiveRowRanges(rowNumbers) .toReversed() .map(({ endRow, startRow }) => ({ deleteDimension: { range: { dimension: "ROWS", endIndex: endRow, sheetId: source.sheetId, startIndex: startRow - 1, }, }, })), }, spreadsheetId, }) return { affectedCells: rowNumbers.length * source.columnCount, rowNumbers, } })