import * as z from "zod" import { defineAction } from "../../../automation/actions" import { getGoogleSheetsApi, normalizeSheet, normalizeSpreadsheetId, resolveSheet, } from "../lib/google-sheets" import { GOOGLE_SHEETS_WRITE_REQUIREMENT } from "../lib/scopes" import { SHEET_REFERENCE_SCHEMA, SHEET_SCHEMA, SPREADSHEET_REFERENCE_SCHEMA, } from "../lib/schemas" /** Duplicates a sheet within the same spreadsheet. */ export const duplicateGoogleSheet = defineAction("Duplicate Google sheet") .describe("Copies a sheet, including its values and formatting.") .account("google", GOOGLE_SHEETS_WRITE_REQUIREMENT) .input( z.object({ /** Optional zero-based insertion position for the copy. */ index: z.number().int().nonnegative().optional(), /** Optional title for the copy. */ newTitle: z.string().trim().min(1).optional(), /** Sheet title or immutable numeric sheet ID. */ sheet: SHEET_REFERENCE_SCHEMA, /** Spreadsheet ID or standard Google Sheets URL. */ spreadsheet: SPREADSHEET_REFERENCE_SCHEMA, }), ) .output(SHEET_SCHEMA) .retry({ replaySafety: "unsafe" }) .handler(async ({ account, input }) => { const spreadsheetId = normalizeSpreadsheetId(input.spreadsheet) const sheetsApi = getGoogleSheetsApi(account.secret) const { data } = await sheetsApi.spreadsheets.batchUpdate({ requestBody: { requests: [ { duplicateSheet: { insertSheetIndex: input.index, newSheetName: input.newTitle, sourceSheetId: ( await resolveSheet(sheetsApi, spreadsheetId, input.sheet) ).properties!.sheetId!, }, }, ], }, spreadsheetId, }) const properties = data.replies?.[0]?.duplicateSheet?.properties if (!properties) { throw new Error("Google did not return the duplicated sheet.") } return normalizeSheet({ properties, tables: [] }) })