import * as z from "zod" import { defineAction } from "../../../automation/actions" import { getGoogleSheetsApi, normalizeSpreadsheetId, readSourceRows, resolveRowSource, } from "../lib/google-sheets" import { GOOGLE_SHEETS_READ_REQUIREMENT } from "../lib/scopes" import { ROW_SOURCE_SCHEMA, SHEET_ROW_SCHEMA, SPREADSHEET_REFERENCE_SCHEMA, VALUE_RENDER_SCHEMA, } from "../lib/schemas" /** Lists consecutive header-keyed rows from the beginning or end of a source. */ export const listGoogleSheetsRows = defineAction("List Google Sheets rows") .describe("Lists a bounded page of rows from a sheet or native table.") .account("google", GOOGLE_SHEETS_READ_REQUIREMENT) .input( z.object({ /** Whether paging begins at the top or bottom of the data. */ from: z.enum(["start", "end"]).optional(), /** Maximum number of rows returned. */ limit: z.number().int().min(1).max(10_000).optional(), /** Rows skipped from the selected end before returning results. */ offset: z.number().int().nonnegative().optional(), /** Header-backed sheet or native table. */ source: ROW_SOURCE_SCHEMA, /** Spreadsheet ID or standard Google Sheets URL. */ spreadsheet: SPREADSHEET_REFERENCE_SCHEMA, /** How formulas and formatted cells are represented. */ valueRender: VALUE_RENDER_SCHEMA.optional(), }), ) .output(SHEET_ROW_SCHEMA.array()) .retry({ replaySafety: "safe" }) .handler(async ({ account, input }) => { const sheetsApi = getGoogleSheetsApi(account.secret) const spreadsheetId = normalizeSpreadsheetId(input.spreadsheet) const source = await resolveRowSource( sheetsApi, spreadsheetId, input.source, ) const limit = input.limit ?? 100 const offset = input.offset ?? 0 if (input.from !== "end") { const startRow = source.bodyStartRow + offset return readSourceRows(sheetsApi, spreadsheetId, source, { endRow: Math.min( startRow + limit - 1, source.bodyEndRow ?? Number.MAX_SAFE_INTEGER, ), startRow, valueRender: input.valueRender, }) } const rows = await readSourceRows(sheetsApi, spreadsheetId, source, { valueRender: input.valueRender, }) return rows.slice( Math.max(0, rows.length - offset - limit), rows.length - offset, ) })