@budibase/server 1.3.21 → 1.3.22-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mocks__/mongodb.ts +1 -1
- package/builder/assets/index.96c69636.js +1008 -0
- package/builder/assets/index.c167b5c3.css +6 -0
- package/builder/index.html +2 -4
- package/coverage/clover.xml +308 -338
- package/coverage/coverage-final.json +19 -21
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +41 -8
- package/coverage/lcov-report/api/controllers/automation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/backup.js.html +1 -1
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +73 -34
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +27 -57
- package/coverage/lcov-report/api/controllers/integration.js.html +6 -6
- package/coverage/lcov-report/api/controllers/layout.js.html +1 -1
- package/coverage/lcov-report/api/controllers/metadata.js.html +1 -1
- package/coverage/lcov-report/api/controllers/migrations.js.html +1 -1
- package/coverage/lcov-report/api/controllers/permission.js.html +1 -1
- package/coverage/lcov-report/api/controllers/query/index.html +1 -1
- package/coverage/lcov-report/api/controllers/query/validation.js.html +1 -1
- package/coverage/lcov-report/api/controllers/role.js.html +1 -1
- package/coverage/lcov-report/api/controllers/routing.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/external.js.html +2 -2
- package/coverage/lcov-report/api/controllers/row/index.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/script.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/bulkFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/external.js.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.html +1 -1
- package/coverage/lcov-report/api/controllers/table/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/templates.js.html +1 -1
- package/coverage/lcov-report/api/controllers/user.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/exporters.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.html +1 -1
- package/coverage/lcov-report/api/controllers/view/index.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/utils.js.html +1 -1
- package/coverage/lcov-report/api/controllers/view/viewBuilder.js.html +1 -1
- package/coverage/lcov-report/api/controllers/webhook.js.html +1 -1
- package/coverage/lcov-report/api/index.html +1 -1
- package/coverage/lcov-report/api/index.js.html +13 -13
- package/coverage/lcov-report/api/routes/analytics.js.html +1 -1
- package/coverage/lcov-report/api/routes/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/routes/auth.js.html +1 -1
- package/coverage/lcov-report/api/routes/automation.js.html +1 -1
- package/coverage/lcov-report/api/routes/backup.js.html +1 -1
- package/coverage/lcov-report/api/routes/cloud.js.html +1 -1
- package/coverage/lcov-report/api/routes/component.js.html +1 -1
- package/coverage/lcov-report/api/routes/datasource.js.html +1 -1
- package/coverage/lcov-report/api/routes/deploy.js.html +1 -1
- package/coverage/lcov-report/api/routes/dev.js.html +1 -1
- package/coverage/lcov-report/api/routes/index.html +1 -1
- package/coverage/lcov-report/api/routes/integration.js.html +1 -1
- package/coverage/lcov-report/api/routes/layout.js.html +1 -1
- package/coverage/lcov-report/api/routes/metadata.js.html +1 -1
- package/coverage/lcov-report/api/routes/migrations.js.html +1 -1
- package/coverage/lcov-report/api/routes/permission.js.html +1 -1
- package/coverage/lcov-report/api/routes/query.js.html +1 -1
- package/coverage/lcov-report/api/routes/role.js.html +1 -1
- package/coverage/lcov-report/api/routes/routing.js.html +1 -1
- package/coverage/lcov-report/api/routes/screen.js.html +1 -1
- package/coverage/lcov-report/api/routes/script.js.html +1 -1
- package/coverage/lcov-report/api/routes/table.js.html +2 -2
- package/coverage/lcov-report/api/routes/templates.js.html +1 -1
- package/coverage/lcov-report/api/routes/user.js.html +1 -1
- package/coverage/lcov-report/api/routes/utils/index.html +9 -9
- package/coverage/lcov-report/api/routes/utils/validators.js.html +75 -12
- package/coverage/lcov-report/api/routes/view.js.html +1 -1
- package/coverage/lcov-report/api/routes/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/actions.js.html +1 -1
- package/coverage/lcov-report/automations/automationUtils.js.html +1 -1
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +1 -1
- package/coverage/lcov-report/automations/index.js.html +1 -1
- package/coverage/lcov-report/automations/steps/bash.js.html +1 -1
- package/coverage/lcov-report/automations/steps/delay.js.html +1 -1
- package/coverage/lcov-report/automations/steps/discord.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeQuery.js.html +1 -1
- package/coverage/lcov-report/automations/steps/executeScript.js.html +1 -1
- package/coverage/lcov-report/automations/steps/filter.js.html +1 -1
- package/coverage/lcov-report/automations/steps/index.html +1 -1
- package/coverage/lcov-report/automations/steps/integromat.js.html +1 -1
- package/coverage/lcov-report/automations/steps/loop.js.html +1 -1
- package/coverage/lcov-report/automations/steps/outgoingWebhook.js.html +1 -1
- package/coverage/lcov-report/automations/steps/queryRows.js.html +1 -1
- package/coverage/lcov-report/automations/steps/sendSmtpEmail.js.html +1 -1
- package/coverage/lcov-report/automations/steps/serverLog.js.html +1 -1
- package/coverage/lcov-report/automations/steps/slack.js.html +1 -1
- package/coverage/lcov-report/automations/steps/updateRow.js.html +1 -1
- package/coverage/lcov-report/automations/steps/utils.js.html +1 -1
- package/coverage/lcov-report/automations/steps/zapier.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/app.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/cron.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/index.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowDeleted.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowSaved.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/rowUpdated.js.html +1 -1
- package/coverage/lcov-report/automations/triggerInfo/webhook.js.html +1 -1
- package/coverage/lcov-report/automations/triggers.js.html +1 -1
- package/coverage/lcov-report/constants/index.html +1 -1
- package/coverage/lcov-report/constants/index.js.html +1 -1
- package/coverage/lcov-report/constants/layouts.js.html +1 -1
- package/coverage/lcov-report/constants/screens.js.html +1 -1
- package/coverage/lcov-report/db/inMemoryView.js.html +1 -1
- package/coverage/lcov-report/db/index.html +14 -14
- package/coverage/lcov-report/db/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/LinkController.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.html +1 -1
- package/coverage/lcov-report/db/linkedRows/index.js.html +1 -1
- package/coverage/lcov-report/db/linkedRows/linkUtils.js.html +1 -1
- package/coverage/lcov-report/db/newid.js.html +2 -2
- package/coverage/lcov-report/db/utils.js.html +30 -18
- package/coverage/lcov-report/events/AutomationEmitter.js.html +3 -3
- package/coverage/lcov-report/events/index.html +1 -1
- package/coverage/lcov-report/events/index.js.html +1 -1
- package/coverage/lcov-report/events/utils.js.html +1 -1
- package/coverage/lcov-report/index.html +44 -44
- package/coverage/lcov-report/integrations/tests/TestConfiguration.js.html +1 -1
- package/coverage/lcov-report/integrations/tests/index.html +1 -1
- package/coverage/lcov-report/middleware/appInfo.js.html +1 -1
- package/coverage/lcov-report/middleware/builder.js.html +12 -12
- package/coverage/lcov-report/middleware/currentapp.js.html +46 -40
- package/coverage/lcov-report/middleware/index.html +15 -15
- package/coverage/lcov-report/middleware/joi-validator.js.html +1 -1
- package/coverage/lcov-report/middleware/publicApi.js.html +1 -1
- package/coverage/lcov-report/middleware/resourceId.js.html +7 -7
- package/coverage/lcov-report/middleware/selfhost.js.html +1 -1
- package/coverage/lcov-report/middleware/utils.js.html +2 -2
- package/coverage/lcov-report/utilities/budibaseDir.js.html +3 -3
- package/coverage/lcov-report/utilities/centralPath.js.html +4 -4
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +16 -16
- package/coverage/lcov-report/utilities/index.html +15 -15
- package/coverage/lcov-report/utilities/index.js.html +24 -24
- package/coverage/lcov-report/utilities/queue/inMemoryQueue.js.html +2 -2
- package/coverage/lcov-report/utilities/queue/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.html +1 -1
- package/coverage/lcov-report/utilities/routing/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/index.js.html +1 -1
- package/coverage/lcov-report/utilities/rowProcessor/utils.js.html +1 -1
- package/coverage/lcov-report/utilities/scriptRunner.js.html +1 -1
- package/coverage/lcov-report/utilities/security.js.html +2 -2
- package/coverage/lcov-report/utilities/statusCodes.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/index.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/rows.js.html +1 -1
- package/coverage/lcov-report/utilities/usageQuota/usageQuoteReset.js.html +1 -1
- package/coverage/lcov-report/utilities/users.js.html +1 -1
- package/coverage/lcov-report/utilities/workerRequests.js.html +32 -8
- package/coverage/lcov.info +521 -558
- package/dist/api/controllers/application.js +5 -5
- package/dist/api/controllers/auth.js +9 -0
- package/dist/api/controllers/component.js +19 -6
- package/dist/api/controllers/datasource.js +21 -8
- package/dist/api/controllers/deploy/index.js +1 -8
- package/dist/api/controllers/integration.js +4 -4
- package/dist/{migrations/functions/usageQuotas/syncDevelopers.js → api/controllers/plugin/file.js} +13 -13
- package/dist/api/controllers/plugin/github.js +69 -0
- package/dist/api/controllers/plugin/index.js +144 -0
- package/dist/api/controllers/plugin/npm.js +58 -0
- package/dist/api/controllers/plugin/uploaders.js +11 -0
- package/dist/{migrations/functions/usageQuotas/syncPublishedApps.js → api/controllers/plugin/url.js} +13 -15
- package/dist/api/controllers/plugin/utils.js +26 -0
- package/dist/api/controllers/row/external.js +1 -1
- package/dist/api/controllers/screen.js +62 -14
- package/dist/api/controllers/static/index.js +1 -0
- package/dist/api/controllers/static/templates/BudibaseApp.svelte +10 -0
- package/dist/api/controllers/static/templates/preview.hbs +5 -1
- package/dist/api/index.js +1 -1
- package/dist/api/routes/application.js +3 -2
- package/dist/api/routes/index.js +2 -0
- package/dist/{migrations/functions/publishedAppsQuota.js → api/routes/plugin.js} +13 -21
- package/dist/api/routes/public/rows.js +1 -82
- package/dist/api/routes/public/tables.js +1 -1
- package/dist/api/routes/table.js +1 -1
- package/dist/api/routes/utils/validators.js +20 -2
- package/dist/app.js +16 -1
- package/dist/db/utils.js +3 -0
- package/dist/environment.js +1 -0
- package/dist/integrations/airtable.js +126 -129
- package/dist/integrations/arangodb.js +86 -89
- package/dist/integrations/base/query.js +2 -2
- package/dist/integrations/base/sqlTable.js +3 -1
- package/dist/integrations/couchdb.js +80 -83
- package/dist/integrations/dynamodb.js +161 -164
- package/dist/integrations/elasticsearch.js +135 -138
- package/dist/integrations/firebase.js +154 -157
- package/dist/integrations/googlesheets.js +323 -327
- package/dist/integrations/index.js +99 -51
- package/dist/integrations/microsoftSqlServer.js +240 -243
- package/dist/integrations/mongodb.js +239 -242
- package/dist/integrations/mysql.js +215 -219
- package/dist/integrations/oracle.js +318 -322
- package/dist/integrations/postgres.js +262 -265
- package/dist/integrations/redis.js +134 -139
- package/dist/integrations/rest.js +289 -292
- package/dist/integrations/s3.js +61 -64
- package/dist/integrations/snowflake.js +83 -86
- package/dist/middleware/currentapp.js +2 -0
- package/dist/migrations/functions/backfill/global.js +0 -3
- package/dist/migrations/index.js +0 -10
- package/dist/package.json +9 -6
- package/dist/tests/utilities/TestConfiguration.js +1 -1
- package/dist/threads/query.js +2 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/index.js +105 -1
- package/dist/utilities/workerRequests.js +4 -0
- package/dist/watch.js +77 -0
- package/dist/websocket.js +22 -0
- package/package.json +10 -7
- package/scripts/dev/manage.js +4 -0
- package/scripts/localdomain.js +3 -1
- package/specs/openapi.json +115 -112
- package/specs/openapi.yaml +96 -94
- package/specs/resources/misc.js +116 -0
- package/specs/resources/query.js +1 -1
- package/src/api/controllers/application.ts +1 -2
- package/src/api/controllers/auth.js +11 -0
- package/src/api/controllers/component.ts +57 -0
- package/src/api/controllers/datasource.js +21 -8
- package/src/api/controllers/deploy/index.ts +1 -6
- package/src/api/controllers/integration.js +4 -4
- package/src/api/controllers/plugin/file.ts +15 -0
- package/src/api/controllers/plugin/github.ts +75 -0
- package/src/api/controllers/plugin/index.ts +134 -0
- package/src/api/controllers/plugin/npm.ts +56 -0
- package/src/api/controllers/plugin/uploaders.ts +4 -0
- package/src/api/controllers/plugin/url.ts +12 -0
- package/src/api/controllers/plugin/utils.ts +19 -0
- package/src/api/controllers/public/mapping/types.ts +8 -0
- package/src/api/controllers/row/external.js +1 -1
- package/src/api/controllers/screen.ts +122 -0
- package/src/api/controllers/static/index.ts +1 -1
- package/src/api/controllers/static/templates/BudibaseApp.svelte +10 -0
- package/src/api/controllers/static/templates/preview.hbs +5 -1
- package/src/api/index.js +1 -1
- package/src/api/routes/application.ts +13 -2
- package/src/api/routes/index.ts +2 -0
- package/src/api/routes/plugin.ts +14 -0
- package/src/api/routes/public/rows.ts +1 -82
- package/src/api/routes/public/tables.ts +1 -1
- package/src/api/routes/table.js +1 -1
- package/src/api/routes/tests/query.spec.js +8 -25
- package/src/api/routes/tests/user.spec.js +0 -2
- package/src/api/routes/utils/validators.js +26 -5
- package/src/app.ts +25 -2
- package/src/db/utils.js +4 -0
- package/src/definitions/openapi.ts +56 -55
- package/src/environment.js +1 -0
- package/src/integrations/airtable.ts +116 -118
- package/src/integrations/arangodb.ts +87 -89
- package/src/integrations/base/query.ts +2 -2
- package/src/integrations/base/sqlTable.ts +3 -1
- package/src/integrations/couchdb.ts +83 -89
- package/src/integrations/dynamodb.ts +173 -175
- package/src/integrations/elasticsearch.ts +120 -122
- package/src/integrations/firebase.ts +157 -159
- package/src/integrations/googlesheets.ts +328 -338
- package/src/integrations/index.ts +64 -21
- package/src/integrations/microsoftSqlServer.ts +249 -251
- package/src/integrations/mongodb.ts +261 -258
- package/src/integrations/mysql.ts +229 -234
- package/src/integrations/oracle.ts +373 -380
- package/src/integrations/postgres.ts +264 -268
- package/src/integrations/redis.ts +128 -132
- package/src/integrations/rest.ts +324 -329
- package/src/integrations/s3.ts +68 -71
- package/src/integrations/snowflake.ts +80 -82
- package/src/integrations/tests/{airtable.spec.js → airtable.spec.ts} +21 -18
- package/src/integrations/tests/{arangodb.spec.js → arangodb.spec.ts} +12 -9
- package/src/integrations/tests/{couchdb.spec.js → couchdb.spec.ts} +33 -27
- package/src/integrations/tests/{dynamodb.spec.js → dynamodb.spec.ts} +45 -41
- package/src/integrations/tests/{elasticsearch.spec.js → elasticsearch.spec.ts} +22 -21
- package/src/integrations/tests/{firebase.spec.js → firebase.spec.ts} +33 -28
- package/src/integrations/tests/{microsoftSqlServer.spec.js → microsoftSqlServer.spec.ts} +12 -11
- package/src/integrations/tests/{mongo.spec.js → mongo.spec.ts} +46 -35
- package/src/integrations/tests/{mysql.spec.js → mysql.spec.ts} +17 -15
- package/src/integrations/tests/{oracle.spec.js → oracle.spec.ts} +19 -17
- package/src/integrations/tests/{postgres.spec.js → postgres.spec.ts} +19 -17
- package/src/integrations/tests/{redis.spec.js → redis.spec.ts} +27 -18
- package/src/integrations/tests/{rest.spec.js → rest.spec.ts} +22 -14
- package/src/integrations/tests/{s3.spec.js → s3.spec.ts} +10 -8
- package/src/integrations/tests/{sql.spec.js → sql.spec.ts} +228 -177
- package/src/middleware/currentapp.js +2 -0
- package/src/migrations/functions/backfill/global.ts +0 -3
- package/src/migrations/index.ts +0 -16
- package/src/module.d.ts +2 -0
- package/src/tests/utilities/TestConfiguration.js +1 -1
- package/src/threads/query.ts +2 -2
- package/src/utilities/fileSystem/index.js +123 -0
- package/src/utilities/workerRequests.js +8 -0
- package/src/watch.ts +38 -0
- package/src/websocket.ts +26 -0
- package/builder/assets/index.8d12d461.css +0 -6
- package/builder/assets/index.d354271c.js +0 -879
- package/builder/assets/vendor.5e1fe644.css +0 -1
- package/builder/assets/vendor.67dbd8fa.js +0 -248
- package/coverage/lcov-report/api/controllers/component.js.html +0 -199
- package/coverage/lcov-report/api/controllers/screen.js.html +0 -259
- package/dist/migrations/functions/developerQuota.js +0 -49
- package/src/api/controllers/component.js +0 -38
- package/src/api/controllers/screen.js +0 -58
- package/src/migrations/functions/developerQuota.ts +0 -15
- package/src/migrations/functions/publishedAppsQuota.ts +0 -13
- package/src/migrations/functions/usageQuotas/syncDevelopers.ts +0 -19
- package/src/migrations/functions/usageQuotas/syncPublishedApps.ts +0 -21
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
DatasourceFieldType,
|
|
3
|
+
DatasourcePlus,
|
|
3
4
|
Integration,
|
|
5
|
+
QueryJson,
|
|
4
6
|
QueryType,
|
|
5
7
|
Table,
|
|
6
8
|
TableSchema,
|
|
7
|
-
QueryJson,
|
|
8
|
-
DatasourcePlus,
|
|
9
9
|
} from "@budibase/types"
|
|
10
10
|
import { OAuth2Client } from "google-auth-library"
|
|
11
11
|
import { buildExternalTableId } from "./utils"
|
|
@@ -13,410 +13,400 @@ import { DataSourceOperation, FieldTypes } from "../constants"
|
|
|
13
13
|
import { GoogleSpreadsheet } from "google-spreadsheet"
|
|
14
14
|
import env from "../environment"
|
|
15
15
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const fetch = require("node-fetch")
|
|
16
|
+
const { getGlobalDB } = require("@budibase/backend-core/tenancy")
|
|
17
|
+
const { getScopedConfig } = require("@budibase/backend-core/db")
|
|
18
|
+
const { Configs } = require("@budibase/backend-core/constants")
|
|
19
|
+
const fetch = require("node-fetch")
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
interface GoogleSheetsConfig {
|
|
22
|
+
spreadsheetId: string
|
|
23
|
+
auth: OAuthClientConfig
|
|
24
|
+
}
|
|
26
25
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
interface OAuthClientConfig {
|
|
27
|
+
appId: string
|
|
28
|
+
accessToken: string
|
|
29
|
+
refreshToken: string
|
|
30
|
+
}
|
|
32
31
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
interface AuthTokenRequest {
|
|
33
|
+
client_id: string
|
|
34
|
+
client_secret: string
|
|
35
|
+
refresh_token: string
|
|
36
|
+
}
|
|
38
37
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
interface AuthTokenResponse {
|
|
39
|
+
access_token: string
|
|
40
|
+
}
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
42
|
+
const SCHEMA: Integration = {
|
|
43
|
+
plus: true,
|
|
44
|
+
auth: {
|
|
45
|
+
type: "google",
|
|
46
|
+
},
|
|
47
|
+
relationships: false,
|
|
48
|
+
docs: "https://developers.google.com/sheets/api/quickstart/nodejs",
|
|
49
|
+
description:
|
|
50
|
+
"Create and collaborate on online spreadsheets in real-time and from any device. ",
|
|
51
|
+
friendlyName: "Google Sheets",
|
|
52
|
+
type: "Spreadsheet",
|
|
53
|
+
datasource: {
|
|
54
|
+
spreadsheetId: {
|
|
55
|
+
display: "Google Sheet URL",
|
|
56
|
+
type: DatasourceFieldType.STRING,
|
|
57
|
+
required: true,
|
|
47
58
|
},
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
+
},
|
|
60
|
+
query: {
|
|
61
|
+
create: {
|
|
62
|
+
type: QueryType.FIELDS,
|
|
63
|
+
fields: {
|
|
64
|
+
sheet: {
|
|
65
|
+
type: DatasourceFieldType.STRING,
|
|
66
|
+
required: true,
|
|
67
|
+
},
|
|
68
|
+
row: {
|
|
69
|
+
type: QueryType.JSON,
|
|
70
|
+
required: true,
|
|
71
|
+
},
|
|
59
72
|
},
|
|
60
73
|
},
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
required: true,
|
|
68
|
-
},
|
|
69
|
-
row: {
|
|
70
|
-
type: QueryType.JSON,
|
|
71
|
-
required: true,
|
|
72
|
-
},
|
|
74
|
+
read: {
|
|
75
|
+
type: QueryType.FIELDS,
|
|
76
|
+
fields: {
|
|
77
|
+
sheet: {
|
|
78
|
+
type: DatasourceFieldType.STRING,
|
|
79
|
+
required: true,
|
|
73
80
|
},
|
|
74
81
|
},
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
+
},
|
|
83
|
+
update: {
|
|
84
|
+
type: QueryType.FIELDS,
|
|
85
|
+
fields: {
|
|
86
|
+
sheet: {
|
|
87
|
+
type: DatasourceFieldType.STRING,
|
|
88
|
+
required: true,
|
|
82
89
|
},
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
},
|
|
91
|
-
rowIndex: {
|
|
92
|
-
type: DatasourceFieldType.STRING,
|
|
93
|
-
required: true,
|
|
94
|
-
},
|
|
95
|
-
row: {
|
|
96
|
-
type: QueryType.JSON,
|
|
97
|
-
required: true,
|
|
98
|
-
},
|
|
90
|
+
rowIndex: {
|
|
91
|
+
type: DatasourceFieldType.STRING,
|
|
92
|
+
required: true,
|
|
93
|
+
},
|
|
94
|
+
row: {
|
|
95
|
+
type: QueryType.JSON,
|
|
96
|
+
required: true,
|
|
99
97
|
},
|
|
100
98
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
99
|
+
},
|
|
100
|
+
delete: {
|
|
101
|
+
type: QueryType.FIELDS,
|
|
102
|
+
fields: {
|
|
103
|
+
sheet: {
|
|
104
|
+
type: DatasourceFieldType.STRING,
|
|
105
|
+
required: true,
|
|
106
|
+
},
|
|
107
|
+
rowIndex: {
|
|
108
|
+
type: DatasourceFieldType.NUMBER,
|
|
109
|
+
required: true,
|
|
112
110
|
},
|
|
113
111
|
},
|
|
114
112
|
},
|
|
113
|
+
},
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
class GoogleSheetsIntegration implements DatasourcePlus {
|
|
117
|
+
private readonly config: GoogleSheetsConfig
|
|
118
|
+
private client: any
|
|
119
|
+
public tables: Record<string, Table> = {}
|
|
120
|
+
public schemaErrors: Record<string, string> = {}
|
|
121
|
+
|
|
122
|
+
constructor(config: GoogleSheetsConfig) {
|
|
123
|
+
this.config = config
|
|
124
|
+
const spreadsheetId = this.cleanSpreadsheetUrl(this.config.spreadsheetId)
|
|
125
|
+
this.client = new GoogleSpreadsheet(spreadsheetId)
|
|
115
126
|
}
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
public tables: Record<string, Table> = {}
|
|
121
|
-
public schemaErrors: Record<string, string> = {}
|
|
128
|
+
getBindingIdentifier() {
|
|
129
|
+
return ""
|
|
130
|
+
}
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
this.client = new GoogleSpreadsheet(spreadsheetId)
|
|
127
|
-
}
|
|
132
|
+
getStringConcat(parts: string[]) {
|
|
133
|
+
return ""
|
|
134
|
+
}
|
|
128
135
|
|
|
129
|
-
|
|
130
|
-
|
|
136
|
+
/**
|
|
137
|
+
* Pull the spreadsheet ID out from a valid google sheets URL
|
|
138
|
+
* @param spreadsheetId - the URL or standard spreadsheetId of the google sheet
|
|
139
|
+
* @returns spreadsheet Id of the google sheet
|
|
140
|
+
*/
|
|
141
|
+
cleanSpreadsheetUrl(spreadsheetId: string) {
|
|
142
|
+
if (!spreadsheetId) {
|
|
143
|
+
throw new Error(
|
|
144
|
+
"You must set a spreadsheet ID in your configuration to fetch tables."
|
|
145
|
+
)
|
|
131
146
|
}
|
|
147
|
+
const parts = spreadsheetId.split("/")
|
|
148
|
+
return parts.length > 5 ? parts[5] : spreadsheetId
|
|
149
|
+
}
|
|
132
150
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
151
|
+
async fetchAccessToken(
|
|
152
|
+
payload: AuthTokenRequest
|
|
153
|
+
): Promise<AuthTokenResponse> {
|
|
154
|
+
const response = await fetch("https://www.googleapis.com/oauth2/v4/token", {
|
|
155
|
+
method: "POST",
|
|
156
|
+
body: JSON.stringify({
|
|
157
|
+
...payload,
|
|
158
|
+
grant_type: "refresh_token",
|
|
159
|
+
}),
|
|
160
|
+
headers: {
|
|
161
|
+
"Content-Type": "application/json",
|
|
162
|
+
},
|
|
163
|
+
})
|
|
136
164
|
|
|
137
|
-
|
|
138
|
-
* Pull the spreadsheet ID out from a valid google sheets URL
|
|
139
|
-
* @param spreadsheetId - the URL or standard spreadsheetId of the google sheet
|
|
140
|
-
* @returns spreadsheet Id of the google sheet
|
|
141
|
-
*/
|
|
142
|
-
cleanSpreadsheetUrl(spreadsheetId: string) {
|
|
143
|
-
if (!spreadsheetId) {
|
|
144
|
-
throw new Error(
|
|
145
|
-
"You must set a spreadsheet ID in your configuration to fetch tables."
|
|
146
|
-
)
|
|
147
|
-
}
|
|
148
|
-
const parts = spreadsheetId.split("/")
|
|
149
|
-
return parts.length > 5 ? parts[5] : spreadsheetId
|
|
150
|
-
}
|
|
165
|
+
const json = await response.json()
|
|
151
166
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
const response = await fetch(
|
|
156
|
-
"https://www.googleapis.com/oauth2/v4/token",
|
|
157
|
-
{
|
|
158
|
-
method: "POST",
|
|
159
|
-
body: JSON.stringify({
|
|
160
|
-
...payload,
|
|
161
|
-
grant_type: "refresh_token",
|
|
162
|
-
}),
|
|
163
|
-
headers: {
|
|
164
|
-
"Content-Type": "application/json",
|
|
165
|
-
},
|
|
166
|
-
}
|
|
167
|
+
if (response.status !== 200) {
|
|
168
|
+
throw new Error(
|
|
169
|
+
`Error authenticating with google sheets. ${json.error_description}`
|
|
167
170
|
)
|
|
171
|
+
}
|
|
168
172
|
|
|
169
|
-
|
|
173
|
+
return json
|
|
174
|
+
}
|
|
170
175
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
176
|
+
async connect() {
|
|
177
|
+
try {
|
|
178
|
+
// Initialise oAuth client
|
|
179
|
+
const db = getGlobalDB()
|
|
180
|
+
let googleConfig = await getScopedConfig(db, {
|
|
181
|
+
type: Configs.GOOGLE,
|
|
182
|
+
})
|
|
183
|
+
|
|
184
|
+
if (!googleConfig) {
|
|
185
|
+
googleConfig = {
|
|
186
|
+
clientID: env.GOOGLE_CLIENT_ID,
|
|
187
|
+
clientSecret: env.GOOGLE_CLIENT_SECRET,
|
|
188
|
+
}
|
|
175
189
|
}
|
|
176
190
|
|
|
177
|
-
|
|
191
|
+
const oauthClient = new OAuth2Client({
|
|
192
|
+
clientId: googleConfig.clientID,
|
|
193
|
+
clientSecret: googleConfig.clientSecret,
|
|
194
|
+
})
|
|
195
|
+
|
|
196
|
+
const tokenResponse = await this.fetchAccessToken({
|
|
197
|
+
client_id: googleConfig.clientID,
|
|
198
|
+
client_secret: googleConfig.clientSecret,
|
|
199
|
+
refresh_token: this.config.auth.refreshToken,
|
|
200
|
+
})
|
|
201
|
+
|
|
202
|
+
oauthClient.setCredentials({
|
|
203
|
+
refresh_token: this.config.auth.refreshToken,
|
|
204
|
+
access_token: tokenResponse.access_token,
|
|
205
|
+
})
|
|
206
|
+
|
|
207
|
+
this.client.useOAuth2Client(oauthClient)
|
|
208
|
+
await this.client.loadInfo()
|
|
209
|
+
} catch (err) {
|
|
210
|
+
console.error("Error connecting to google sheets", err)
|
|
211
|
+
throw err
|
|
178
212
|
}
|
|
213
|
+
}
|
|
179
214
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
215
|
+
async buildSchema(datasourceId: string) {
|
|
216
|
+
await this.connect()
|
|
217
|
+
const sheets = await this.client.sheetsByIndex
|
|
218
|
+
const tables: Record<string, Table> = {}
|
|
219
|
+
for (let sheet of sheets) {
|
|
220
|
+
// must fetch rows to determine schema
|
|
221
|
+
await sheet.getRows()
|
|
222
|
+
// build schema
|
|
223
|
+
const schema: TableSchema = {}
|
|
224
|
+
|
|
225
|
+
// build schema from headers
|
|
226
|
+
for (let header of sheet.headerValues) {
|
|
227
|
+
schema[header] = {
|
|
228
|
+
name: header,
|
|
229
|
+
type: FieldTypes.STRING,
|
|
193
230
|
}
|
|
231
|
+
}
|
|
194
232
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
client_id: googleConfig.clientID,
|
|
202
|
-
client_secret: googleConfig.clientSecret,
|
|
203
|
-
refresh_token: this.config.auth.refreshToken,
|
|
204
|
-
})
|
|
205
|
-
|
|
206
|
-
oauthClient.setCredentials({
|
|
207
|
-
refresh_token: this.config.auth.refreshToken,
|
|
208
|
-
access_token: tokenResponse.access_token,
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
this.client.useOAuth2Client(oauthClient)
|
|
212
|
-
await this.client.loadInfo()
|
|
213
|
-
} catch (err) {
|
|
214
|
-
console.error("Error connecting to google sheets", err)
|
|
215
|
-
throw err
|
|
233
|
+
// create tables
|
|
234
|
+
tables[sheet.title] = {
|
|
235
|
+
_id: buildExternalTableId(datasourceId, sheet.title),
|
|
236
|
+
name: sheet.title,
|
|
237
|
+
primary: ["rowNumber"],
|
|
238
|
+
schema,
|
|
216
239
|
}
|
|
217
240
|
}
|
|
218
241
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
const sheets = await this.client.sheetsByIndex
|
|
222
|
-
const tables: Record<string, Table> = {}
|
|
223
|
-
for (let sheet of sheets) {
|
|
224
|
-
// must fetch rows to determine schema
|
|
225
|
-
await sheet.getRows()
|
|
226
|
-
// build schema
|
|
227
|
-
const schema: TableSchema = {}
|
|
228
|
-
|
|
229
|
-
// build schema from headers
|
|
230
|
-
for (let header of sheet.headerValues) {
|
|
231
|
-
schema[header] = {
|
|
232
|
-
name: header,
|
|
233
|
-
type: FieldTypes.STRING,
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
// create tables
|
|
238
|
-
tables[sheet.title] = {
|
|
239
|
-
_id: buildExternalTableId(datasourceId, sheet.title),
|
|
240
|
-
name: sheet.title,
|
|
241
|
-
primary: ["rowNumber"],
|
|
242
|
-
schema,
|
|
243
|
-
}
|
|
244
|
-
}
|
|
242
|
+
this.tables = tables
|
|
243
|
+
}
|
|
245
244
|
|
|
246
|
-
|
|
245
|
+
async query(json: QueryJson) {
|
|
246
|
+
const sheet = json.endpoint.entityId
|
|
247
|
+
|
|
248
|
+
const handlers = {
|
|
249
|
+
[DataSourceOperation.CREATE]: () =>
|
|
250
|
+
this.create({ sheet, row: json.body }),
|
|
251
|
+
[DataSourceOperation.READ]: () => this.read({ sheet }),
|
|
252
|
+
[DataSourceOperation.UPDATE]: () =>
|
|
253
|
+
this.update({
|
|
254
|
+
// exclude the header row and zero index
|
|
255
|
+
rowIndex: json.extra?.idFilter?.equal?.rowNumber - 2,
|
|
256
|
+
sheet,
|
|
257
|
+
row: json.body,
|
|
258
|
+
}),
|
|
259
|
+
[DataSourceOperation.DELETE]: () =>
|
|
260
|
+
this.delete({
|
|
261
|
+
// exclude the header row and zero index
|
|
262
|
+
rowIndex: json.extra?.idFilter?.equal?.rowNumber - 2,
|
|
263
|
+
sheet,
|
|
264
|
+
}),
|
|
265
|
+
[DataSourceOperation.CREATE_TABLE]: () =>
|
|
266
|
+
this.createTable(json?.table?.name),
|
|
267
|
+
[DataSourceOperation.UPDATE_TABLE]: () => this.updateTable(json.table),
|
|
268
|
+
[DataSourceOperation.DELETE_TABLE]: () =>
|
|
269
|
+
this.deleteTable(json?.table?.name),
|
|
247
270
|
}
|
|
248
271
|
|
|
249
|
-
|
|
250
|
-
const sheet = json.endpoint.entityId
|
|
251
|
-
|
|
252
|
-
const handlers = {
|
|
253
|
-
[DataSourceOperation.CREATE]: () =>
|
|
254
|
-
this.create({ sheet, row: json.body }),
|
|
255
|
-
[DataSourceOperation.READ]: () => this.read({ sheet }),
|
|
256
|
-
[DataSourceOperation.UPDATE]: () =>
|
|
257
|
-
this.update({
|
|
258
|
-
// exclude the header row and zero index
|
|
259
|
-
rowIndex: json.extra?.idFilter?.equal?.rowNumber - 2,
|
|
260
|
-
sheet,
|
|
261
|
-
row: json.body,
|
|
262
|
-
}),
|
|
263
|
-
[DataSourceOperation.DELETE]: () =>
|
|
264
|
-
this.delete({
|
|
265
|
-
// exclude the header row and zero index
|
|
266
|
-
rowIndex: json.extra?.idFilter?.equal?.rowNumber - 2,
|
|
267
|
-
sheet,
|
|
268
|
-
}),
|
|
269
|
-
[DataSourceOperation.CREATE_TABLE]: () =>
|
|
270
|
-
this.createTable(json?.table?.name),
|
|
271
|
-
[DataSourceOperation.UPDATE_TABLE]: () => this.updateTable(json.table),
|
|
272
|
-
[DataSourceOperation.DELETE_TABLE]: () =>
|
|
273
|
-
this.deleteTable(json?.table?.name),
|
|
274
|
-
}
|
|
272
|
+
const internalQueryMethod = handlers[json.endpoint.operation]
|
|
275
273
|
|
|
276
|
-
|
|
274
|
+
return await internalQueryMethod()
|
|
275
|
+
}
|
|
277
276
|
|
|
278
|
-
|
|
277
|
+
buildRowObject(headers: string[], values: string[], rowNumber: number) {
|
|
278
|
+
const rowObject: { rowNumber: number; [key: string]: any } = { rowNumber }
|
|
279
|
+
for (let i = 0; i < headers.length; i++) {
|
|
280
|
+
rowObject._id = rowNumber
|
|
281
|
+
rowObject[headers[i]] = values[i]
|
|
279
282
|
}
|
|
283
|
+
return rowObject
|
|
284
|
+
}
|
|
280
285
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
286
|
+
async createTable(name?: string) {
|
|
287
|
+
try {
|
|
288
|
+
await this.connect()
|
|
289
|
+
return await this.client.addSheet({ title: name })
|
|
290
|
+
} catch (err) {
|
|
291
|
+
console.error("Error creating new table in google sheets", err)
|
|
292
|
+
throw err
|
|
288
293
|
}
|
|
294
|
+
}
|
|
289
295
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
} catch (err) {
|
|
296
|
-
console.error("Error creating new table in google sheets", err)
|
|
297
|
-
throw err
|
|
298
|
-
}
|
|
299
|
-
}
|
|
296
|
+
async updateTable(table?: any) {
|
|
297
|
+
try {
|
|
298
|
+
await this.connect()
|
|
299
|
+
const sheet = await this.client.sheetsByTitle[table.name]
|
|
300
|
+
await sheet.loadHeaderRow()
|
|
300
301
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
const headers = []
|
|
309
|
-
for (let header of sheet.headerValues) {
|
|
310
|
-
if (header === table._rename.old) {
|
|
311
|
-
headers.push(table._rename.updated)
|
|
312
|
-
} else {
|
|
313
|
-
headers.push(header)
|
|
314
|
-
}
|
|
302
|
+
if (table._rename) {
|
|
303
|
+
const headers = []
|
|
304
|
+
for (let header of sheet.headerValues) {
|
|
305
|
+
if (header === table._rename.old) {
|
|
306
|
+
headers.push(table._rename.updated)
|
|
307
|
+
} else {
|
|
308
|
+
headers.push(header)
|
|
315
309
|
}
|
|
316
|
-
await sheet.setHeaderRow(headers)
|
|
317
|
-
} else {
|
|
318
|
-
let newField = Object.keys(table.schema).find(
|
|
319
|
-
key => !sheet.headerValues.includes(key)
|
|
320
|
-
)
|
|
321
|
-
await sheet.setHeaderRow([...sheet.headerValues, newField])
|
|
322
310
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
async deleteTable(sheet: any) {
|
|
330
|
-
try {
|
|
331
|
-
await this.connect()
|
|
332
|
-
const sheetToDelete = await this.client.sheetsByTitle[sheet]
|
|
333
|
-
return await sheetToDelete.delete()
|
|
334
|
-
} catch (err) {
|
|
335
|
-
console.error("Error deleting table in google sheets", err)
|
|
336
|
-
throw err
|
|
311
|
+
await sheet.setHeaderRow(headers)
|
|
312
|
+
} else {
|
|
313
|
+
let newField = Object.keys(table.schema).find(
|
|
314
|
+
key => !sheet.headerValues.includes(key)
|
|
315
|
+
)
|
|
316
|
+
await sheet.setHeaderRow([...sheet.headerValues, newField])
|
|
337
317
|
}
|
|
318
|
+
} catch (err) {
|
|
319
|
+
console.error("Error updating table in google sheets", err)
|
|
320
|
+
throw err
|
|
338
321
|
}
|
|
322
|
+
}
|
|
339
323
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber),
|
|
349
|
-
]
|
|
350
|
-
} catch (err) {
|
|
351
|
-
console.error("Error writing to google sheets", err)
|
|
352
|
-
throw err
|
|
353
|
-
}
|
|
324
|
+
async deleteTable(sheet: any) {
|
|
325
|
+
try {
|
|
326
|
+
await this.connect()
|
|
327
|
+
const sheetToDelete = await this.client.sheetsByTitle[sheet]
|
|
328
|
+
return await sheetToDelete.delete()
|
|
329
|
+
} catch (err) {
|
|
330
|
+
console.error("Error deleting table in google sheets", err)
|
|
331
|
+
throw err
|
|
354
332
|
}
|
|
333
|
+
}
|
|
355
334
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
} catch (err) {
|
|
370
|
-
console.error("Error reading from google sheets", err)
|
|
371
|
-
throw err
|
|
372
|
-
}
|
|
335
|
+
async create(query: { sheet: string; row: any }) {
|
|
336
|
+
try {
|
|
337
|
+
await this.connect()
|
|
338
|
+
const sheet = await this.client.sheetsByTitle[query.sheet]
|
|
339
|
+
const rowToInsert =
|
|
340
|
+
typeof query.row === "string" ? JSON.parse(query.row) : query.row
|
|
341
|
+
const row = await sheet.addRow(rowToInsert)
|
|
342
|
+
return [
|
|
343
|
+
this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber),
|
|
344
|
+
]
|
|
345
|
+
} catch (err) {
|
|
346
|
+
console.error("Error writing to google sheets", err)
|
|
347
|
+
throw err
|
|
373
348
|
}
|
|
349
|
+
}
|
|
374
350
|
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
}
|
|
387
|
-
await row.save()
|
|
388
|
-
return [
|
|
389
|
-
this.buildRowObject(
|
|
390
|
-
sheet.headerValues,
|
|
391
|
-
row._rawData,
|
|
392
|
-
row._rowNumber
|
|
393
|
-
),
|
|
394
|
-
]
|
|
395
|
-
} else {
|
|
396
|
-
throw new Error("Row does not exist.")
|
|
397
|
-
}
|
|
398
|
-
} catch (err) {
|
|
399
|
-
console.error("Error reading from google sheets", err)
|
|
400
|
-
throw err
|
|
351
|
+
async read(query: { sheet: string }) {
|
|
352
|
+
try {
|
|
353
|
+
await this.connect()
|
|
354
|
+
const sheet = await this.client.sheetsByTitle[query.sheet]
|
|
355
|
+
const rows = await sheet.getRows()
|
|
356
|
+
const headerValues = sheet.headerValues
|
|
357
|
+
const response = []
|
|
358
|
+
for (let row of rows) {
|
|
359
|
+
response.push(
|
|
360
|
+
this.buildRowObject(headerValues, row._rawData, row._rowNumber)
|
|
361
|
+
)
|
|
401
362
|
}
|
|
363
|
+
return response
|
|
364
|
+
} catch (err) {
|
|
365
|
+
console.error("Error reading from google sheets", err)
|
|
366
|
+
throw err
|
|
402
367
|
}
|
|
368
|
+
}
|
|
403
369
|
|
|
404
|
-
|
|
370
|
+
async update(query: { sheet: string; rowIndex: number; row: any }) {
|
|
371
|
+
try {
|
|
405
372
|
await this.connect()
|
|
406
373
|
const sheet = await this.client.sheetsByTitle[query.sheet]
|
|
407
374
|
const rows = await sheet.getRows()
|
|
408
375
|
const row = rows[query.rowIndex]
|
|
409
376
|
if (row) {
|
|
410
|
-
|
|
411
|
-
|
|
377
|
+
const updateValues =
|
|
378
|
+
typeof query.row === "string" ? JSON.parse(query.row) : query.row
|
|
379
|
+
for (let key in updateValues) {
|
|
380
|
+
row[key] = updateValues[key]
|
|
381
|
+
}
|
|
382
|
+
await row.save()
|
|
383
|
+
return [
|
|
384
|
+
this.buildRowObject(sheet.headerValues, row._rawData, row._rowNumber),
|
|
385
|
+
]
|
|
412
386
|
} else {
|
|
413
387
|
throw new Error("Row does not exist.")
|
|
414
388
|
}
|
|
389
|
+
} catch (err) {
|
|
390
|
+
console.error("Error reading from google sheets", err)
|
|
391
|
+
throw err
|
|
415
392
|
}
|
|
416
393
|
}
|
|
417
394
|
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
395
|
+
async delete(query: { sheet: string; rowIndex: number }) {
|
|
396
|
+
await this.connect()
|
|
397
|
+
const sheet = await this.client.sheetsByTitle[query.sheet]
|
|
398
|
+
const rows = await sheet.getRows()
|
|
399
|
+
const row = rows[query.rowIndex]
|
|
400
|
+
if (row) {
|
|
401
|
+
await row.delete()
|
|
402
|
+
return [{ deleted: query.rowIndex }]
|
|
403
|
+
} else {
|
|
404
|
+
throw new Error("Row does not exist.")
|
|
405
|
+
}
|
|
421
406
|
}
|
|
422
407
|
}
|
|
408
|
+
|
|
409
|
+
export default {
|
|
410
|
+
schema: SCHEMA,
|
|
411
|
+
integration: GoogleSheetsIntegration,
|
|
412
|
+
}
|