datasource plus support for google sheets

This commit is contained in:
Martin McKeaveney 2021-11-25 20:12:32 +01:00
parent f9b2a3c5e1
commit 9ac60079c7
1 changed files with 89 additions and 8 deletions

View File

@ -1,10 +1,15 @@
import { import {
DatasourceFieldTypes, DatasourceFieldTypes,
Integration, Integration,
QueryJson,
QueryTypes, QueryTypes,
} from "../definitions/datasource" } from "../definitions/datasource"
import { IntegrationBase } from "./base/IntegrationBase" import { IntegrationBase } from "./base/IntegrationBase"
import { GoogleSpreadsheet } from "google-spreadsheet" 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 { module GoogleSheetsModule {
interface GoogleSheetsConfig { interface GoogleSheetsConfig {
@ -14,6 +19,7 @@ module GoogleSheetsModule {
} }
const SCHEMA: Integration = { const SCHEMA: Integration = {
plus: true,
docs: "https://developers.google.com/sheets/api/quickstart/nodejs", docs: "https://developers.google.com/sheets/api/quickstart/nodejs",
description: description:
"Create and collaborate on online spreadsheets in real-time and from any device. ", "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 readonly config: GoogleSheetsConfig
private client: any private client: any
public tables: Record<string, Table> = {}
public schemaErrors: Record<string, string> = {}
constructor(config: GoogleSheetsConfig) { constructor(config: GoogleSheetsConfig) {
this.config = config this.config = config
@ -112,21 +120,86 @@ module GoogleSheetsModule {
} }
} }
buildRowObject(headers: string[], values: string[]) { async buildSchema(datasourceId: string, entities: Record<string, Table>) {
const rowObject = {} 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++) { for (let i = 0; i < headers.length; i++) {
rowObject[headers[i]] = values[i] rowObject[headers[i]] = values[i]
} }
return rowObject return rowObject
} }
async create(query: { sheet: string; row: string }) { async create(query: { sheet: string; row: string | object }) {
try { try {
await this.connect() await this.connect()
const sheet = await this.client.sheetsByTitle[query.sheet] 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) const row = await sheet.addRow(rowToInsert)
return [this.buildRowObject(sheet.headerValues, row._rawData)] return [
this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber),
]
} catch (err) { } catch (err) {
console.error("Error writing to google sheets", err) console.error("Error writing to google sheets", err)
throw err throw err
@ -141,7 +214,9 @@ module GoogleSheetsModule {
const headerValues = sheet.headerValues const headerValues = sheet.headerValues
const response = [] const response = []
for (let row of rows) { for (let row of rows) {
response.push(this.buildRowObject(headerValues, row._rawData)) response.push(
this.buildRowObject(headerValues, row._rawData, row._rowNumber)
)
} }
return response return response
} catch (err) { } catch (err) {
@ -162,7 +237,13 @@ module GoogleSheetsModule {
row[key] = updateValues[key] row[key] = updateValues[key]
} }
await row.save() await row.save()
return [this.buildRowObject(sheet.headerValues, row._rawData)] return [
this.buildRowObject(
sheet.headerValues,
row._rawData,
row._rowNumber
),
]
} else { } else {
throw new Error("Row does not exist.") throw new Error("Row does not exist.")
} }