/** * Google Sheets client implementation. * * Uses the native Google Sheets plugin type from @superblocksteam/types. */ import type { PartialMessage } from "@bufbuild/protobuf"; import type { z } from "zod"; import type { Plugin as GSheetsPlugin } from "@superblocksteam/types/dist/src/plugins/gsheets/v1/plugin_pb"; import { RestApiValidationError } from "../../errors.js"; import { IntegrationError } from "../../runtime/errors.js"; import type { QueryExecutor, TraceMetadata } from "../registry.js"; import type { IntegrationConfig, IntegrationClientImpl } from "../types.js"; import type { GoogleSheetsClient, GoogleSheetsAction, GoogleSheetsParams, } from "./types.js"; /** * Internal implementation of GoogleSheetsClient. */ export class GoogleSheetsClientImpl implements GoogleSheetsClient, IntegrationClientImpl { readonly config: IntegrationConfig; private readonly executeQuery: QueryExecutor; constructor(config: IntegrationConfig, executeQuery: QueryExecutor) { this.config = config; this.executeQuery = executeQuery; } get name(): string { return this.config.name; } get pluginId(): string { return this.config.pluginId; } private buildRequest( action: GoogleSheetsAction, params: GoogleSheetsParams, ): PartialMessage { const request: PartialMessage = { action, spreadsheetId: params.spreadsheetId, }; if (params.sheetTitle) { request.sheetTitle = params.sheetTitle; } if (params.range) { request.range = params.range; } if (params.rowNumber) { request.rowNumber = params.rowNumber; } if (params.extractFirstRowHeader !== undefined) { request.extractFirstRowHeader = params.extractFirstRowHeader; } if (params.headerRowNumber) { request.headerRowNumber = params.headerRowNumber; } if (params.format) { request.format = params.format; } if (params.data) { request.data = params.data; } if (params.preserveHeaderRow !== undefined) { request.preserveHeaderRow = params.preserveHeaderRow; } if (params.includeHeaderRow !== undefined) { request.includeHeaderRow = params.includeHeaderRow; } if (params.writeToDestinationType) { request.writeToDestinationType = params.writeToDestinationType; } if (params.body) { request.body = params.body; } if (params.addSheet) { request.addSheet = { sheetTitle: params.addSheet.sheetTitle, rowCount: params.addSheet.rowCount, columnCount: params.addSheet.columnCount, }; } return request; } async run( action: GoogleSheetsAction, schema: z.ZodSchema, params: GoogleSheetsParams, metadata?: TraceMetadata, ): Promise { const request = this.buildRequest(action, params); try { const result = await this.executeQuery( request as Record, undefined, metadata, ); // Validate result against schema const parseResult = schema.safeParse(result); if (!parseResult.success) { throw new RestApiValidationError( `Result validation failed: ${parseResult.error.message}`, { zodError: parseResult.error, data: result, }, ); } return parseResult.data; } catch (error) { if ( error instanceof RestApiValidationError || error instanceof IntegrationError ) { throw error; } throw new IntegrationError(this.config.name, "run", error); } } }