@budibase/server 1.3.21-alpha.1 → 1.3.21

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