diff --git a/packages/server/src/integrations/googlesheets.ts b/packages/server/src/integrations/googlesheets.ts index eaffd98277..514804a73e 100644 --- a/packages/server/src/integrations/googlesheets.ts +++ b/packages/server/src/integrations/googlesheets.ts @@ -1,10 +1,15 @@ import { DatasourceFieldTypes, Integration, + QueryJson, QueryTypes, } from "../definitions/datasource" import { IntegrationBase } from "./base/IntegrationBase" import { GoogleSpreadsheet } from "google-spreadsheet" +import { DatasourcePlus } from "./base/datasourcePlus" +import { Table } from "../definitions/common" +import { buildExternalTableId } from "./utils" +import { DataSourceOperation, FieldTypes } from "../constants" module GoogleSheetsModule { interface GoogleSheetsConfig { @@ -14,6 +19,7 @@ module GoogleSheetsModule { } const SCHEMA: Integration = { + plus: true, docs: "https://developers.google.com/sheets/api/quickstart/nodejs", description: "Create and collaborate on online spreadsheets in real-time and from any device. ", @@ -88,9 +94,11 @@ module GoogleSheetsModule { }, } - class GoogleSheetsIntegration implements IntegrationBase { + class GoogleSheetsIntegration implements DatasourcePlus { private readonly config: GoogleSheetsConfig private client: any + public tables: Record = {} + public schemaErrors: Record = {} constructor(config: GoogleSheetsConfig) { this.config = config @@ -112,21 +120,86 @@ module GoogleSheetsModule { } } - buildRowObject(headers: string[], values: string[]) { - const rowObject = {} + async buildSchema(datasourceId: string, entities: Record) { + await this.connect() + const sheets = await this.client.sheetsByIndex + const tables = {} + // tables[tableName] = { + // _id: buildExternalTableId(datasourceId, tableName), + // primary: primaryKeys, + // name: tableName, + // schema, + // } + for (let sheet of sheets) { + // must fetch rows to determine schema + await sheet.getRows() + // build schema + const schema = {} + + // build schema from headers + for (let header of sheet.headerValues) { + schema[header] = { + name: header, + type: FieldTypes.STRING, + } + } + + // create tables + tables[sheet.title] = { + _id: buildExternalTableId(datasourceId, sheet.title), + name: sheet.title, + primary: ["rowNumber"], + schema, + } + } + + this.tables = tables + } + + async query(json: QueryJson) { + const sheet = json.endpoint.entityId + + if (json.endpoint.operation === DataSourceOperation.CREATE) { + return await this.create({ + sheet, + row: json.body, + }) + } + + if (json.endpoint.operation === DataSourceOperation.READ) { + return await this.read({ sheet }) + } + + if (json.endpoint.operation === DataSourceOperation.UPDATE) { + return await this.update({ + sheet, + row: json.body, + }) + } + + if (json.endpoint.operation === DataSourceOperation.DELETE) { + return await this.delete({}) + } + } + + buildRowObject(headers: string[], values: string[], rowNumber: number) { + const rowObject = { rowNumber } for (let i = 0; i < headers.length; i++) { rowObject[headers[i]] = values[i] } return rowObject } - async create(query: { sheet: string; row: string }) { + async create(query: { sheet: string; row: string | object }) { try { await this.connect() const sheet = await this.client.sheetsByTitle[query.sheet] - const rowToInsert = JSON.parse(query.row) + const rowToInsert = + typeof query.row === "string" ? JSON.parse(query.row) : query.row const row = await sheet.addRow(rowToInsert) - return [this.buildRowObject(sheet.headerValues, row._rawData)] + return [ + this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber), + ] } catch (err) { console.error("Error writing to google sheets", err) throw err @@ -141,7 +214,9 @@ module GoogleSheetsModule { const headerValues = sheet.headerValues const response = [] for (let row of rows) { - response.push(this.buildRowObject(headerValues, row._rawData)) + response.push( + this.buildRowObject(headerValues, row._rawData, row._rowNumber) + ) } return response } catch (err) { @@ -162,7 +237,13 @@ module GoogleSheetsModule { row[key] = updateValues[key] } await row.save() - return [this.buildRowObject(sheet.headerValues, row._rawData)] + return [ + this.buildRowObject( + sheet.headerValues, + row._rawData, + row._rowNumber + ), + ] } else { throw new Error("Row does not exist.") }