@budibase/server 1.0.217 → 1.0.219-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__/node-fetch.ts +9 -0
- package/builder/assets/index.7786f497.css +6 -0
- package/builder/assets/index.832d3790.js +977 -0
- package/builder/assets/{vendor.9bf2fcb4.js → vendor.001dcf8c.js} +163 -163
- package/builder/index.html +3 -3
- package/coverage/clover.xml +866 -792
- package/coverage/coverage-final.json +26 -26
- package/coverage/lcov-report/api/controllers/apikeys.js.html +1 -1
- package/coverage/lcov-report/api/controllers/auth.js.html +1 -1
- package/coverage/lcov-report/api/controllers/automation.js.html +111 -12
- package/coverage/lcov-report/api/controllers/backup.js.html +9 -6
- package/coverage/lcov-report/api/controllers/cloud.js.html +1 -1
- package/coverage/lcov-report/api/controllers/component.js.html +1 -1
- package/coverage/lcov-report/api/controllers/datasource.js.html +16 -16
- package/coverage/lcov-report/api/controllers/dev.js.html +1 -1
- package/coverage/lcov-report/api/controllers/index.html +21 -21
- package/coverage/lcov-report/api/controllers/integration.js.html +1 -1
- 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 +47 -17
- package/coverage/lcov-report/api/controllers/row/index.html +34 -34
- package/coverage/lcov-report/api/controllers/row/internal.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/internalSearch.js.html +95 -11
- package/coverage/lcov-report/api/controllers/row/staticFormula.js.html +1 -1
- package/coverage/lcov-report/api/controllers/row/utils.js.html +17 -8
- package/coverage/lcov-report/api/controllers/screen.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 +15 -15
- package/coverage/lcov-report/api/index.js.html +22 -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 +32 -2
- 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 +1 -1
- 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 +1 -1
- package/coverage/lcov-report/api/routes/utils/validators.js.html +1 -1
- 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 +57 -12
- package/coverage/lcov-report/automations/bullboard.js.html +1 -1
- package/coverage/lcov-report/automations/index.html +17 -17
- 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 +58 -34
- package/coverage/lcov-report/automations/steps/index.html +11 -11
- 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 +4 -4
- 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 +13 -13
- package/coverage/lcov-report/db/linkedRows/index.js.html +10 -7
- 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 +27 -51
- package/coverage/lcov-report/events/AutomationEmitter.js.html +1 -1
- 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 +74 -74
- 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 +33 -33
- package/coverage/lcov-report/middleware/index.html +1 -1
- package/coverage/lcov-report/middleware/joi-validator.js.html +10 -10
- 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/threads/automation.js.html +18 -9
- package/coverage/lcov-report/threads/index.html +25 -25
- package/coverage/lcov-report/threads/query.js.html +280 -76
- package/coverage/lcov-report/threads/utils.js.html +4 -4
- package/coverage/lcov-report/utilities/budibaseDir.js.html +1 -1
- package/coverage/lcov-report/utilities/centralPath.js.html +1 -1
- package/coverage/lcov-report/utilities/csvParser.js.html +1 -1
- package/coverage/lcov-report/utilities/global.js.html +14 -14
- package/coverage/lcov-report/utilities/index.html +1 -1
- package/coverage/lcov-report/utilities/index.js.html +9 -9
- 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 +1 -1
- package/coverage/lcov.info +1554 -1422
- package/dist/api/controllers/application.js +18 -15
- package/dist/api/controllers/automation.js +28 -2
- package/dist/api/controllers/backup.js +3 -2
- package/dist/api/controllers/query/index.js +25 -0
- package/dist/api/controllers/row/external.js +19 -7
- package/dist/api/controllers/row/internalSearch.js +22 -1
- package/dist/api/controllers/row/utils.js +3 -0
- package/dist/api/index.js +4 -1
- package/dist/api/routes/automation.js +2 -0
- package/dist/automations/automationUtils.js +16 -4
- package/dist/automations/logging/index.js +70 -0
- package/dist/automations/steps/filter.js +38 -29
- package/dist/automations/triggers.js +1 -1
- package/dist/db/linkedRows/index.js +1 -0
- package/dist/db/utils.js +4 -31
- package/dist/definitions/datasource.js +1 -0
- package/dist/environment.js +1 -0
- package/dist/integrations/airtable.js +1 -0
- package/dist/integrations/arangodb.js +1 -0
- package/dist/integrations/base/sql.js +20 -3
- package/dist/integrations/couchdb.js +1 -0
- package/dist/integrations/dynamodb.js +1 -0
- package/dist/integrations/elasticsearch.js +1 -0
- package/dist/integrations/firebase.js +1 -0
- package/dist/integrations/googlesheets.js +1 -0
- package/dist/integrations/index.js +4 -0
- package/dist/integrations/microsoftSqlServer.js +2 -1
- package/dist/integrations/mongodb.js +1 -0
- package/dist/integrations/mysql.js +2 -1
- package/dist/integrations/oracle.js +1 -0
- package/dist/integrations/postgres.js +2 -1
- package/dist/integrations/queries/sql.js +3 -0
- package/dist/integrations/redis.js +1 -0
- package/dist/integrations/rest.js +2 -1
- package/dist/integrations/s3.js +1 -0
- package/dist/integrations/snowflake.js +102 -0
- package/dist/package.json +7 -6
- package/dist/tests/utilities/TestConfiguration.js +19 -6
- package/dist/threads/automation.js +6 -3
- package/dist/threads/index.js +15 -1
- package/dist/threads/query.js +53 -8
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utilities/fileSystem/index.js +16 -6
- package/package.json +8 -7
- package/scripts/integrations/oracle/instantclient/linux/arm64/basiclite-19.10.zip +0 -0
- package/scripts/integrations/oracle/instantclient/linux/arm64/install.sh +23 -0
- package/scripts/integrations/oracle/instantclient/linux/install.sh +10 -0
- package/src/api/controllers/application.ts +18 -14
- package/src/api/controllers/automation.js +35 -2
- package/src/api/controllers/backup.js +3 -2
- package/src/api/controllers/query/index.ts +29 -1
- package/src/api/controllers/row/external.js +19 -9
- package/src/api/controllers/row/internalSearch.js +28 -0
- package/src/api/controllers/row/utils.js +3 -0
- package/src/api/index.js +4 -1
- package/src/api/routes/automation.js +10 -0
- package/src/api/routes/tests/query.spec.js +166 -0
- package/src/automations/automationUtils.js +19 -4
- package/src/automations/logging/index.ts +35 -0
- package/src/automations/steps/filter.js +36 -28
- package/src/automations/tests/filter.spec.js +2 -1
- package/src/automations/triggers.js +1 -1
- package/src/db/linkedRows/index.js +1 -0
- package/src/db/utils.js +5 -13
- package/src/definitions/common.ts +1 -0
- package/src/definitions/datasource.ts +2 -0
- package/src/environment.js +1 -0
- package/src/integrations/airtable.ts +1 -0
- package/src/integrations/arangodb.ts +1 -0
- package/src/integrations/base/sql.ts +25 -11
- package/src/integrations/couchdb.ts +1 -0
- package/src/integrations/dynamodb.ts +1 -0
- package/src/integrations/elasticsearch.ts +1 -0
- package/src/integrations/firebase.ts +1 -0
- package/src/integrations/googlesheets.ts +1 -0
- package/src/integrations/index.ts +4 -0
- package/src/integrations/microsoftSqlServer.ts +2 -0
- package/src/integrations/mongodb.ts +1 -0
- package/src/integrations/mysql.ts +2 -0
- package/src/integrations/oracle.ts +1 -0
- package/src/integrations/postgres.ts +2 -0
- package/src/integrations/queries/sql.ts +3 -1
- package/src/integrations/redis.ts +1 -0
- package/src/integrations/rest.ts +2 -1
- package/src/integrations/s3.ts +1 -0
- package/src/integrations/snowflake.ts +99 -0
- package/src/integrations/tests/rest.spec.js +16 -1
- package/src/migrations/tests/index.spec.ts +18 -2
- package/src/module.d.ts +2 -0
- package/src/tests/utilities/TestConfiguration.js +22 -3
- package/src/threads/automation.js +6 -3
- package/src/threads/index.ts +5 -1
- package/src/threads/query.js +78 -10
- package/src/utilities/fileSystem/index.js +22 -8
- package/builder/assets/index.24307ca0.css +0 -6
- package/builder/assets/index.cc2e9cbe.js +0 -1316
|
@@ -89,6 +89,23 @@ function parseFilters(filters) {
|
|
|
89
89
|
}
|
|
90
90
|
return filters;
|
|
91
91
|
}
|
|
92
|
+
function generateSelectStatement(json, knex) {
|
|
93
|
+
var _a;
|
|
94
|
+
const { resource, meta } = json;
|
|
95
|
+
const schema = (_a = meta === null || meta === void 0 ? void 0 : meta.table) === null || _a === void 0 ? void 0 : _a.schema;
|
|
96
|
+
return resource.fields.map(field => {
|
|
97
|
+
const fieldNames = field.split(/\./g);
|
|
98
|
+
const tableName = fieldNames[0];
|
|
99
|
+
const columnName = fieldNames[1];
|
|
100
|
+
if (columnName && knex.client.config.client === utils_1.SqlClients.POSTGRES) {
|
|
101
|
+
const externalType = schema === null || schema === void 0 ? void 0 : schema[columnName].externalType;
|
|
102
|
+
if (externalType === null || externalType === void 0 ? void 0 : externalType.includes("money")) {
|
|
103
|
+
return knex.raw(`"${tableName}"."${columnName}"::money::numeric as "${field}"`);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return `${field} as ${field}`;
|
|
107
|
+
});
|
|
108
|
+
}
|
|
92
109
|
class InternalBuilder {
|
|
93
110
|
constructor(client) {
|
|
94
111
|
this.client = client;
|
|
@@ -209,7 +226,7 @@ class InternalBuilder {
|
|
|
209
226
|
}
|
|
210
227
|
return query;
|
|
211
228
|
}
|
|
212
|
-
addRelationships(
|
|
229
|
+
addRelationships(query, fromTable, relationships) {
|
|
213
230
|
if (!relationships) {
|
|
214
231
|
return query;
|
|
215
232
|
}
|
|
@@ -311,7 +328,7 @@ class InternalBuilder {
|
|
|
311
328
|
if (resource.fields && resource.fields.length > 0) {
|
|
312
329
|
// select the resources as the format "table.columnName" - this is what is provided
|
|
313
330
|
// by the resource builder further up
|
|
314
|
-
selectStatement =
|
|
331
|
+
selectStatement = generateSelectStatement(json, knex);
|
|
315
332
|
}
|
|
316
333
|
let foundLimit = limit || BASE_LIMIT;
|
|
317
334
|
// handle pagination
|
|
@@ -347,7 +364,7 @@ class InternalBuilder {
|
|
|
347
364
|
preQuery = this.addSorting(preQuery, json);
|
|
348
365
|
}
|
|
349
366
|
// handle joins
|
|
350
|
-
query = this.addRelationships(
|
|
367
|
+
query = this.addRelationships(preQuery, tableName, relationships);
|
|
351
368
|
return this.addFilters(query, filters, { relationship: true });
|
|
352
369
|
}
|
|
353
370
|
update(knex, json, opts) {
|
|
@@ -16,6 +16,7 @@ var CouchDBModule;
|
|
|
16
16
|
const SCHEMA = {
|
|
17
17
|
docs: "https://docs.couchdb.org/en/stable/",
|
|
18
18
|
friendlyName: "CouchDB",
|
|
19
|
+
type: "Non-relational",
|
|
19
20
|
description: "Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.",
|
|
20
21
|
datasource: {
|
|
21
22
|
url: {
|
|
@@ -18,6 +18,7 @@ var DynamoModule;
|
|
|
18
18
|
docs: "https://github.com/dabit3/dynamodb-documentclient-cheat-sheet",
|
|
19
19
|
description: "Amazon DynamoDB is a key-value and document database that delivers single-digit millisecond performance at any scale.",
|
|
20
20
|
friendlyName: "DynamoDB",
|
|
21
|
+
type: "Non-relational",
|
|
21
22
|
datasource: {
|
|
22
23
|
region: {
|
|
23
24
|
type: datasource_1.DatasourceFieldTypes.STRING,
|
|
@@ -17,6 +17,7 @@ var ElasticsearchModule;
|
|
|
17
17
|
docs: "https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/current/index.html",
|
|
18
18
|
description: "Elasticsearch is a search engine based on the Lucene library. It provides a distributed, multitenant-capable full-text search engine with an HTTP web interface and schema-free JSON documents.",
|
|
19
19
|
friendlyName: "ElasticSearch",
|
|
20
|
+
type: "Non-relational",
|
|
20
21
|
datasource: {
|
|
21
22
|
url: {
|
|
22
23
|
type: datasource_1.DatasourceFieldTypes.STRING,
|
|
@@ -16,6 +16,7 @@ var Firebase;
|
|
|
16
16
|
const SCHEMA = {
|
|
17
17
|
docs: "https://firebase.google.com/docs/firestore/quickstart",
|
|
18
18
|
friendlyName: "Firestore",
|
|
19
|
+
type: "Non-relational",
|
|
19
20
|
description: "Cloud Firestore is a flexible, scalable database for mobile, web, and server development from Firebase and Google Cloud.",
|
|
20
21
|
datasource: {
|
|
21
22
|
email: {
|
|
@@ -33,6 +33,7 @@ var GoogleSheetsModule;
|
|
|
33
33
|
docs: "https://developers.google.com/sheets/api/quickstart/nodejs",
|
|
34
34
|
description: "Create and collaborate on online spreadsheets in real-time and from any device. ",
|
|
35
35
|
friendlyName: "Google Sheets",
|
|
36
|
+
type: "Spreadsheet",
|
|
36
37
|
datasource: {
|
|
37
38
|
spreadsheetId: {
|
|
38
39
|
display: "Google Sheet URL",
|
|
@@ -13,6 +13,7 @@ const rest = require("./rest");
|
|
|
13
13
|
const googlesheets = require("./googlesheets");
|
|
14
14
|
const firebase = require("./firebase");
|
|
15
15
|
const redis = require("./redis");
|
|
16
|
+
const snowflake = require("./snowflake");
|
|
16
17
|
const { SourceNames } = require("../definitions/datasource");
|
|
17
18
|
const environment = require("../environment");
|
|
18
19
|
const DEFINITIONS = {
|
|
@@ -29,6 +30,7 @@ const DEFINITIONS = {
|
|
|
29
30
|
[SourceNames.REST]: rest.schema,
|
|
30
31
|
[SourceNames.FIRESTORE]: firebase.schema,
|
|
31
32
|
[SourceNames.REDIS]: redis.schema,
|
|
33
|
+
[SourceNames.SNOWFLAKE]: snowflake.schema,
|
|
32
34
|
};
|
|
33
35
|
const INTEGRATIONS = {
|
|
34
36
|
[SourceNames.POSTGRES]: postgres.integration,
|
|
@@ -45,6 +47,8 @@ const INTEGRATIONS = {
|
|
|
45
47
|
[SourceNames.FIRESTORE]: firebase.integration,
|
|
46
48
|
[SourceNames.GOOGLE_SHEETS]: googlesheets.integration,
|
|
47
49
|
[SourceNames.REDIS]: redis.integration,
|
|
50
|
+
[SourceNames.FIREBASE]: firebase.integration,
|
|
51
|
+
[SourceNames.SNOWFLAKE]: snowflake.integration,
|
|
48
52
|
};
|
|
49
53
|
// optionally add oracle integration if the oracle binary can be installed
|
|
50
54
|
if (!(process.arch === "arm64" && process.platform === "darwin")) {
|
|
@@ -21,6 +21,7 @@ var MSSQLModule;
|
|
|
21
21
|
plus: true,
|
|
22
22
|
description: "Microsoft SQL Server is a relational database management system developed by Microsoft. ",
|
|
23
23
|
friendlyName: "MS SQL Server",
|
|
24
|
+
type: "Relational",
|
|
24
25
|
datasource: {
|
|
25
26
|
user: {
|
|
26
27
|
type: datasource_1.DatasourceFieldTypes.STRING,
|
|
@@ -201,7 +202,7 @@ var MSSQLModule;
|
|
|
201
202
|
if (typeof name !== "string") {
|
|
202
203
|
continue;
|
|
203
204
|
}
|
|
204
|
-
schema[name] = Object.assign({ autocolumn: !!autoColumns.find((col) => col === name), name: name }, (0, utils_1.convertSqlType)(def.DATA_TYPE));
|
|
205
|
+
schema[name] = Object.assign(Object.assign({ autocolumn: !!autoColumns.find((col) => col === name), name: name }, (0, utils_1.convertSqlType)(def.DATA_TYPE)), { externalType: def.DATA_TYPE });
|
|
205
206
|
}
|
|
206
207
|
tables[tableName] = {
|
|
207
208
|
_id: (0, utils_1.buildExternalTableId)(datasourceId, tableName),
|
|
@@ -16,6 +16,7 @@ var MongoDBModule;
|
|
|
16
16
|
const SCHEMA = {
|
|
17
17
|
docs: "https://github.com/mongodb/node-mongodb-native",
|
|
18
18
|
friendlyName: "MongoDB",
|
|
19
|
+
type: "Non-relational",
|
|
19
20
|
description: "MongoDB is a general purpose, document-based, distributed database built for modern application developers and for the cloud era.",
|
|
20
21
|
datasource: {
|
|
21
22
|
connectionString: {
|
|
@@ -24,6 +24,7 @@ var MySQLModule;
|
|
|
24
24
|
docs: "https://github.com/sidorares/node-mysql2",
|
|
25
25
|
plus: true,
|
|
26
26
|
friendlyName: "MySQL",
|
|
27
|
+
type: "Relational",
|
|
27
28
|
description: "MySQL Database Service is a fully managed database service to deploy cloud-native applications. ",
|
|
28
29
|
datasource: {
|
|
29
30
|
host: {
|
|
@@ -187,7 +188,7 @@ var MySQLModule;
|
|
|
187
188
|
const isAuto = typeof column.Extra === "string" &&
|
|
188
189
|
(column.Extra === "auto_increment" ||
|
|
189
190
|
column.Extra.toLowerCase().includes("generated"));
|
|
190
|
-
schema[columnName] = Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type));
|
|
191
|
+
schema[columnName] = Object.assign(Object.assign({ name: columnName, autocolumn: isAuto, constraints }, (0, utils_1.convertSqlType)(column.Type)), { externalType: column.Type });
|
|
191
192
|
}
|
|
192
193
|
if (!tables[tableName]) {
|
|
193
194
|
tables[tableName] = {
|
|
@@ -24,6 +24,7 @@ var OracleModule;
|
|
|
24
24
|
docs: "https://github.com/oracle/node-oracledb",
|
|
25
25
|
plus: true,
|
|
26
26
|
friendlyName: "Oracle",
|
|
27
|
+
type: "Relational",
|
|
27
28
|
description: "Oracle Database is an object-relational database management system developed by Oracle Corporation",
|
|
28
29
|
datasource: {
|
|
29
30
|
host: {
|
|
@@ -29,6 +29,7 @@ var PostgresModule;
|
|
|
29
29
|
docs: "https://node-postgres.com",
|
|
30
30
|
plus: true,
|
|
31
31
|
friendlyName: "PostgreSQL",
|
|
32
|
+
type: "Relational",
|
|
32
33
|
description: "PostgreSQL, also known as Postgres, is a free and open-source relational database management system emphasizing extensibility and SQL compliance.",
|
|
33
34
|
datasource: {
|
|
34
35
|
host: {
|
|
@@ -229,7 +230,7 @@ var PostgresModule;
|
|
|
229
230
|
column.column_default.startsWith("nextval");
|
|
230
231
|
const isGenerated = column.is_generated && column.is_generated !== "NEVER";
|
|
231
232
|
const isAuto = hasDefault || identity || isGenerated;
|
|
232
|
-
tables[tableName].schema[columnName] = Object.assign({ autocolumn: isAuto, name: columnName }, (0, utils_1.convertSqlType)(column.data_type));
|
|
233
|
+
tables[tableName].schema[columnName] = Object.assign(Object.assign({ autocolumn: isAuto, name: columnName }, (0, utils_1.convertSqlType)(column.data_type)), { externalType: column.data_type });
|
|
233
234
|
}
|
|
234
235
|
const final = (0, utils_1.finaliseExternalTables)(tables, entities);
|
|
235
236
|
this.tables = final.tables;
|
|
@@ -5,6 +5,9 @@ const string_templates_1 = require("@budibase/string-templates");
|
|
|
5
5
|
const CONST_CHAR_REGEX = new RegExp("'[^']*'", "g");
|
|
6
6
|
function enrichQueryFields(fields, parameters = {}) {
|
|
7
7
|
const enrichedQuery = Array.isArray(fields) ? [] : {};
|
|
8
|
+
if (!fields || !parameters) {
|
|
9
|
+
return enrichedQuery;
|
|
10
|
+
}
|
|
8
11
|
// enrich the fields with dynamic parameters
|
|
9
12
|
for (let key of Object.keys(fields)) {
|
|
10
13
|
if (fields[key] == null) {
|
|
@@ -56,6 +56,7 @@ var RestModule;
|
|
|
56
56
|
docs: "https://github.com/node-fetch/node-fetch",
|
|
57
57
|
description: "With the REST API datasource, you can connect, query and pull data from multiple REST APIs. You can then use the retrieved data to build apps.",
|
|
58
58
|
friendlyName: "REST API",
|
|
59
|
+
type: "API",
|
|
59
60
|
datasource: {
|
|
60
61
|
url: {
|
|
61
62
|
type: datasource_1.DatasourceFieldTypes.STRING,
|
|
@@ -251,7 +252,7 @@ var RestModule;
|
|
|
251
252
|
input.body = form;
|
|
252
253
|
break;
|
|
253
254
|
case BodyTypes.XML:
|
|
254
|
-
if (object != null) {
|
|
255
|
+
if (object != null && Object.keys(object).length) {
|
|
255
256
|
string = new XmlBuilder().buildObject(object);
|
|
256
257
|
}
|
|
257
258
|
input.body = string;
|
package/dist/integrations/s3.js
CHANGED
|
@@ -17,6 +17,7 @@ var S3Module;
|
|
|
17
17
|
docs: "https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
|
18
18
|
description: "Amazon Simple Storage Service (Amazon S3) is an object storage service that offers industry-leading scalability, data availability, security, and performance.",
|
|
19
19
|
friendlyName: "Amazon S3",
|
|
20
|
+
type: "Object store",
|
|
20
21
|
datasource: {
|
|
21
22
|
region: {
|
|
22
23
|
type: "string",
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
const datasource_1 = require("../definitions/datasource");
|
|
13
|
+
const snowflake_promise_1 = require("snowflake-promise");
|
|
14
|
+
var SnowflakeModule;
|
|
15
|
+
(function (SnowflakeModule) {
|
|
16
|
+
const SCHEMA = {
|
|
17
|
+
docs: "https://developers.snowflake.com/",
|
|
18
|
+
description: "Snowflake is a solution for data warehousing, data lakes, data engineering, data science, data application development, and securely sharing and consuming shared data.",
|
|
19
|
+
friendlyName: "Snowflake",
|
|
20
|
+
type: "Relational",
|
|
21
|
+
datasource: {
|
|
22
|
+
account: {
|
|
23
|
+
type: "string",
|
|
24
|
+
required: true,
|
|
25
|
+
},
|
|
26
|
+
username: {
|
|
27
|
+
type: "string",
|
|
28
|
+
required: true,
|
|
29
|
+
},
|
|
30
|
+
password: {
|
|
31
|
+
type: "password",
|
|
32
|
+
required: true,
|
|
33
|
+
},
|
|
34
|
+
warehouse: {
|
|
35
|
+
type: "string",
|
|
36
|
+
required: true,
|
|
37
|
+
},
|
|
38
|
+
database: {
|
|
39
|
+
type: "string",
|
|
40
|
+
required: true,
|
|
41
|
+
},
|
|
42
|
+
schema: {
|
|
43
|
+
type: "string",
|
|
44
|
+
required: true,
|
|
45
|
+
},
|
|
46
|
+
},
|
|
47
|
+
query: {
|
|
48
|
+
create: {
|
|
49
|
+
type: datasource_1.QueryTypes.SQL,
|
|
50
|
+
},
|
|
51
|
+
read: {
|
|
52
|
+
type: datasource_1.QueryTypes.SQL,
|
|
53
|
+
},
|
|
54
|
+
update: {
|
|
55
|
+
type: datasource_1.QueryTypes.SQL,
|
|
56
|
+
},
|
|
57
|
+
delete: {
|
|
58
|
+
type: datasource_1.QueryTypes.SQL,
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
class SnowflakeIntegration {
|
|
63
|
+
constructor(config) {
|
|
64
|
+
this.client = new snowflake_promise_1.Snowflake(config);
|
|
65
|
+
}
|
|
66
|
+
internalQuery(query) {
|
|
67
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
68
|
+
yield this.client.connect();
|
|
69
|
+
try {
|
|
70
|
+
return yield this.client.execute(query.sql);
|
|
71
|
+
}
|
|
72
|
+
catch (err) {
|
|
73
|
+
throw (err === null || err === void 0 ? void 0 : err.message.split(":")[1]) || (err === null || err === void 0 ? void 0 : err.message);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
create(query) {
|
|
78
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
79
|
+
return this.internalQuery(query);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
read(query) {
|
|
83
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
84
|
+
return this.internalQuery(query);
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
update(query) {
|
|
88
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
89
|
+
return this.internalQuery(query);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
delete(query) {
|
|
93
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
94
|
+
return this.internalQuery(query);
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
module.exports = {
|
|
99
|
+
schema: SCHEMA,
|
|
100
|
+
integration: SnowflakeIntegration,
|
|
101
|
+
};
|
|
102
|
+
})(SnowflakeModule || (SnowflakeModule = {}));
|
package/dist/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.219-alpha.0",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -77,10 +77,11 @@
|
|
|
77
77
|
"license": "GPL-3.0",
|
|
78
78
|
"dependencies": {
|
|
79
79
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
80
|
-
"@budibase/backend-core": "^1.0.
|
|
81
|
-
"@budibase/client": "^1.0.
|
|
82
|
-
"@budibase/pro": "1.0.
|
|
83
|
-
"@budibase/string-templates": "^1.0.
|
|
80
|
+
"@budibase/backend-core": "^1.0.219-alpha.0",
|
|
81
|
+
"@budibase/client": "^1.0.219-alpha.0",
|
|
82
|
+
"@budibase/pro": "1.0.219-alpha.0",
|
|
83
|
+
"@budibase/string-templates": "^1.0.219-alpha.0",
|
|
84
|
+
"@budibase/types": "^1.0.219-alpha.0",
|
|
84
85
|
"@bull-board/api": "3.7.0",
|
|
85
86
|
"@bull-board/koa": "3.9.4",
|
|
86
87
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -135,6 +136,7 @@
|
|
|
135
136
|
"pouchdb-replication-stream": "1.2.9",
|
|
136
137
|
"redis": "4",
|
|
137
138
|
"server-destroy": "1.0.1",
|
|
139
|
+
"snowflake-promise": "^4.5.0",
|
|
138
140
|
"svelte": "3.44.1",
|
|
139
141
|
"swagger-parser": "10.0.3",
|
|
140
142
|
"to-json-schema": "0.2.5",
|
|
@@ -150,7 +152,6 @@
|
|
|
150
152
|
"@babel/core": "7.17.4",
|
|
151
153
|
"@babel/preset-env": "7.16.11",
|
|
152
154
|
"@budibase/standard-components": "^0.9.139",
|
|
153
|
-
"@budibase/types": "^1.0.216",
|
|
154
155
|
"@jest/test-sequencer": "24.9.0",
|
|
155
156
|
"@types/apidoc": "0.50.0",
|
|
156
157
|
"@types/bson": "4.2.0",
|
|
@@ -26,6 +26,8 @@ const { generateDevInfoID, SEPARATOR } = require("@budibase/backend-core/db");
|
|
|
26
26
|
const { encrypt } = require("@budibase/backend-core/encryption");
|
|
27
27
|
const GLOBAL_USER_ID = "us_uuid1";
|
|
28
28
|
const EMAIL = "babs@babs.com";
|
|
29
|
+
const FIRSTNAME = "Barbara";
|
|
30
|
+
const LASTNAME = "Barbington";
|
|
29
31
|
const CSRF_TOKEN = "e3727778-7af0-4226-b5eb-f43cbe60a306";
|
|
30
32
|
class TestConfiguration {
|
|
31
33
|
constructor(openServer = true) {
|
|
@@ -51,6 +53,14 @@ class TestConfiguration {
|
|
|
51
53
|
getProdAppId() {
|
|
52
54
|
return this.prodAppId;
|
|
53
55
|
}
|
|
56
|
+
getUserDetails() {
|
|
57
|
+
return {
|
|
58
|
+
globalId: GLOBAL_USER_ID,
|
|
59
|
+
email: EMAIL,
|
|
60
|
+
firstName: FIRSTNAME,
|
|
61
|
+
lastName: LASTNAME,
|
|
62
|
+
};
|
|
63
|
+
}
|
|
54
64
|
doInContext(appId, task) {
|
|
55
65
|
return __awaiter(this, void 0, void 0, function* () {
|
|
56
66
|
if (!appId) {
|
|
@@ -109,7 +119,7 @@ class TestConfiguration {
|
|
|
109
119
|
});
|
|
110
120
|
}
|
|
111
121
|
// USER / AUTH
|
|
112
|
-
globalUser({ id = GLOBAL_USER_ID, builder = true, admin = false, email = EMAIL, roles, } = {}) {
|
|
122
|
+
globalUser({ id = GLOBAL_USER_ID, firstName = FIRSTNAME, lastName = LASTNAME, builder = true, admin = false, email = EMAIL, roles, } = {}) {
|
|
113
123
|
return __awaiter(this, void 0, void 0, function* () {
|
|
114
124
|
return doWithGlobalDB(TENANT_ID, (db) => __awaiter(this, void 0, void 0, function* () {
|
|
115
125
|
let existing;
|
|
@@ -119,7 +129,8 @@ class TestConfiguration {
|
|
|
119
129
|
catch (err) {
|
|
120
130
|
existing = { email };
|
|
121
131
|
}
|
|
122
|
-
const user = Object.assign(Object.assign({ _id: id }, existing), { roles: roles || {}, tenantId: TENANT_ID
|
|
132
|
+
const user = Object.assign(Object.assign({ _id: id }, existing), { roles: roles || {}, tenantId: TENANT_ID, firstName,
|
|
133
|
+
lastName });
|
|
123
134
|
yield createASession(id, {
|
|
124
135
|
sessionId: "sessionid",
|
|
125
136
|
tenantId: TENANT_ID,
|
|
@@ -142,11 +153,13 @@ class TestConfiguration {
|
|
|
142
153
|
}));
|
|
143
154
|
});
|
|
144
155
|
}
|
|
145
|
-
createUser(id = null, email = EMAIL, builder = true, admin = false, roles = {}) {
|
|
156
|
+
createUser(id = null, firstName = FIRSTNAME, lastName = LASTNAME, email = EMAIL, builder = true, admin = false, roles = {}) {
|
|
146
157
|
return __awaiter(this, void 0, void 0, function* () {
|
|
147
158
|
const globalId = !id ? `us_${Math.random()}` : `us_${id}`;
|
|
148
159
|
const resp = yield this.globalUser({
|
|
149
160
|
id: globalId,
|
|
161
|
+
firstName,
|
|
162
|
+
lastName,
|
|
150
163
|
email,
|
|
151
164
|
builder,
|
|
152
165
|
admin,
|
|
@@ -466,15 +479,15 @@ class TestConfiguration {
|
|
|
466
479
|
});
|
|
467
480
|
}
|
|
468
481
|
// QUERY
|
|
469
|
-
previewQuery(request, config, datasource, fields) {
|
|
482
|
+
previewQuery(request, config, datasource, fields, params, verb) {
|
|
470
483
|
return __awaiter(this, void 0, void 0, function* () {
|
|
471
484
|
return request
|
|
472
485
|
.post(`/api/queries/preview`)
|
|
473
486
|
.send({
|
|
474
487
|
datasourceId: datasource._id,
|
|
475
|
-
parameters: {},
|
|
488
|
+
parameters: params || {},
|
|
476
489
|
fields,
|
|
477
|
-
queryVerb: "read",
|
|
490
|
+
queryVerb: verb || "read",
|
|
478
491
|
name: datasource.name,
|
|
479
492
|
})
|
|
480
493
|
.set(config.defaultHeaders())
|
|
@@ -19,10 +19,11 @@ const { doInTenant } = require("@budibase/backend-core/tenancy");
|
|
|
19
19
|
const { definitions: triggerDefs } = require("../automations/triggerInfo");
|
|
20
20
|
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context");
|
|
21
21
|
const { AutomationErrors, LoopStepTypes } = require("../constants");
|
|
22
|
+
const { storeLog } = require("../automations/logging");
|
|
22
23
|
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId;
|
|
23
24
|
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId;
|
|
24
25
|
const CRON_STEP_ID = triggerDefs.CRON.stepId;
|
|
25
|
-
const STOPPED_STATUS = { success:
|
|
26
|
+
const STOPPED_STATUS = { success: true, status: "STOPPED" };
|
|
26
27
|
const { cloneDeep } = require("lodash/fp");
|
|
27
28
|
const env = require("../environment");
|
|
28
29
|
function typecastForLooping(loopStep, input) {
|
|
@@ -195,7 +196,7 @@ class Orchestrator {
|
|
|
195
196
|
}
|
|
196
197
|
}
|
|
197
198
|
}
|
|
198
|
-
if (index ===
|
|
199
|
+
if (index === env.AUTOMATION_MAX_ITERATION ||
|
|
199
200
|
index === parseInt(loopStep.inputs.iterations)) {
|
|
200
201
|
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
|
201
202
|
status: AutomationErrors.MAX_ITERATIONS,
|
|
@@ -248,7 +249,7 @@ class Orchestrator {
|
|
|
248
249
|
this._context.steps[stepCount] = outputs;
|
|
249
250
|
// if filter causes us to stop execution don't break the loop, set a var
|
|
250
251
|
// so that we can finish iterating through the steps and record that it stopped
|
|
251
|
-
if (step.stepId === FILTER_STEP_ID && !outputs.
|
|
252
|
+
if (step.stepId === FILTER_STEP_ID && !outputs.result) {
|
|
252
253
|
stopped = true;
|
|
253
254
|
this.updateExecutionOutput(step.id, step.stepId, step.inputs, Object.assign(Object.assign({}, outputs), STOPPED_STATUS));
|
|
254
255
|
continue;
|
|
@@ -289,6 +290,8 @@ class Orchestrator {
|
|
|
289
290
|
loopSteps = null;
|
|
290
291
|
}
|
|
291
292
|
}
|
|
293
|
+
// store the logs for the automation run
|
|
294
|
+
yield storeLog(this._automation, this.executionOutput);
|
|
292
295
|
return this.executionOutput;
|
|
293
296
|
});
|
|
294
297
|
}
|
package/dist/threads/index.js
CHANGED
|
@@ -22,6 +22,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
22
22
|
__setModuleDefault(result, mod);
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
25
34
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
35
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
36
|
};
|
|
@@ -92,7 +101,7 @@ class Thread {
|
|
|
92
101
|
});
|
|
93
102
|
});
|
|
94
103
|
}
|
|
95
|
-
static
|
|
104
|
+
static stopThreads() {
|
|
96
105
|
return new Promise(resolve => {
|
|
97
106
|
if (Thread.workerRefs.length === 0) {
|
|
98
107
|
resolve();
|
|
@@ -110,6 +119,11 @@ class Thread {
|
|
|
110
119
|
Thread.workerRefs = [];
|
|
111
120
|
});
|
|
112
121
|
}
|
|
122
|
+
static shutdown() {
|
|
123
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
124
|
+
yield Thread.stopThreads();
|
|
125
|
+
});
|
|
126
|
+
}
|
|
113
127
|
}
|
|
114
128
|
exports.Thread = Thread;
|
|
115
129
|
Thread.workerRefs = [];
|
package/dist/threads/query.js
CHANGED
|
@@ -14,6 +14,8 @@ const ScriptRunner = require("../utilities/scriptRunner");
|
|
|
14
14
|
const { integrations } = require("../integrations");
|
|
15
15
|
const { processStringSync } = require("@budibase/string-templates");
|
|
16
16
|
const { doInAppContext, getAppDB } = require("@budibase/backend-core/context");
|
|
17
|
+
const { refreshOAuthToken, updateUserOAuth, } = require("@budibase/backend-core/auth");
|
|
18
|
+
const { getGlobalIDFromUserMetadataID } = require("../db/utils");
|
|
17
19
|
const { isSQL } = require("../integrations/utils");
|
|
18
20
|
const { enrichQueryFields, interpolateSQL, } = require("../integrations/queries/sql");
|
|
19
21
|
class QueryRunner {
|
|
@@ -27,29 +29,46 @@ class QueryRunner {
|
|
|
27
29
|
this.queryId = input.queryId;
|
|
28
30
|
this.noRecursiveQuery = flags.noRecursiveQuery;
|
|
29
31
|
this.cachedVariables = [];
|
|
32
|
+
// Additional context items for enrichment
|
|
33
|
+
this.ctx = input.ctx;
|
|
30
34
|
// allows the response from a query to be stored throughout this
|
|
31
35
|
// execution so that if it needs to be re-used for another variable
|
|
32
36
|
// it can be
|
|
33
37
|
this.queryResponse = {};
|
|
34
38
|
this.hasRerun = false;
|
|
39
|
+
this.hasRefreshedOAuth = false;
|
|
35
40
|
}
|
|
36
41
|
execute() {
|
|
42
|
+
var _a;
|
|
37
43
|
return __awaiter(this, void 0, void 0, function* () {
|
|
38
44
|
let { datasource, fields, queryVerb, transformer } = this;
|
|
39
45
|
const Integration = integrations[datasource.source];
|
|
40
46
|
if (!Integration) {
|
|
41
47
|
throw "Integration type does not exist.";
|
|
42
48
|
}
|
|
49
|
+
if (datasource.config.authConfigs) {
|
|
50
|
+
datasource.config.authConfigs = datasource.config.authConfigs.map(config => {
|
|
51
|
+
return enrichQueryFields(config, this.ctx);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
43
54
|
const integration = new Integration(datasource.config);
|
|
44
55
|
// pre-query, make sure datasource variables are added to parameters
|
|
45
56
|
const parameters = yield this.addDatasourceVariables();
|
|
57
|
+
// Enrich the parameters with the addition context items.
|
|
58
|
+
// 'user' is now a reserved variable key in mapping parameters
|
|
59
|
+
const enrichedParameters = enrichQueryFields(parameters, this.ctx);
|
|
60
|
+
const enrichedContext = Object.assign(Object.assign({}, enrichedParameters), this.ctx);
|
|
61
|
+
// Parse global headers
|
|
62
|
+
if (datasource.config.defaultHeaders) {
|
|
63
|
+
datasource.config.defaultHeaders = enrichQueryFields(datasource.config.defaultHeaders, enrichedContext);
|
|
64
|
+
}
|
|
46
65
|
let query;
|
|
47
66
|
// handle SQL injections by interpolating the variables
|
|
48
67
|
if (isSQL(datasource)) {
|
|
49
|
-
query = interpolateSQL(fields,
|
|
68
|
+
query = interpolateSQL(fields, enrichedParameters, integration);
|
|
50
69
|
}
|
|
51
70
|
else {
|
|
52
|
-
query = enrichQueryFields(fields,
|
|
71
|
+
query = enrichQueryFields(fields, enrichedContext);
|
|
53
72
|
}
|
|
54
73
|
// Add pagination values for REST queries
|
|
55
74
|
if (this.pagination) {
|
|
@@ -67,17 +86,25 @@ class QueryRunner {
|
|
|
67
86
|
if (transformer) {
|
|
68
87
|
const runner = new ScriptRunner(transformer, {
|
|
69
88
|
data: rows,
|
|
70
|
-
params:
|
|
89
|
+
params: enrichedParameters,
|
|
71
90
|
});
|
|
72
91
|
rows = runner.execute();
|
|
73
92
|
}
|
|
74
93
|
// if the request fails we retry once, invalidating the cached value
|
|
75
|
-
if (info &&
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
94
|
+
if (info && info.code >= 400 && !this.hasRerun) {
|
|
95
|
+
if (((_a = this.ctx.user) === null || _a === void 0 ? void 0 : _a.provider) &&
|
|
96
|
+
info.code === 401 &&
|
|
97
|
+
!this.hasRefreshedOAuth) {
|
|
98
|
+
// Attempt to refresh the access token from the provider
|
|
99
|
+
this.hasRefreshedOAuth = true;
|
|
100
|
+
const authResponse = yield this.refreshOAuth2(this.ctx);
|
|
101
|
+
if (!authResponse || authResponse.err) {
|
|
102
|
+
// In this event the user may have oAuth issues that
|
|
103
|
+
// could require re-authenticating with their provider.
|
|
104
|
+
throw new Error("OAuth2 access token could not be refreshed");
|
|
105
|
+
}
|
|
106
|
+
}
|
|
79
107
|
this.hasRerun = true;
|
|
80
|
-
// invalidate the cache value
|
|
81
108
|
yield threadUtils.invalidateDynamicVariables(this.cachedVariables);
|
|
82
109
|
return this.execute();
|
|
83
110
|
}
|
|
@@ -115,6 +142,24 @@ class QueryRunner {
|
|
|
115
142
|
}, { noRecursiveQuery: true }).execute();
|
|
116
143
|
});
|
|
117
144
|
}
|
|
145
|
+
refreshOAuth2(ctx) {
|
|
146
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
147
|
+
const { oauth2, providerType, _id } = ctx.user;
|
|
148
|
+
const { configId } = ctx.auth;
|
|
149
|
+
if (!providerType || !(oauth2 === null || oauth2 === void 0 ? void 0 : oauth2.refreshToken)) {
|
|
150
|
+
console.error("No refresh token found for authenticated user");
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
const resp = yield refreshOAuthToken(oauth2.refreshToken, providerType, configId);
|
|
154
|
+
// Refresh session flow. Should be in same location as refreshOAuthToken
|
|
155
|
+
// There are several other properties available in 'resp'
|
|
156
|
+
if (!resp.error) {
|
|
157
|
+
const globalUserId = getGlobalIDFromUserMetadataID(_id);
|
|
158
|
+
yield updateUserOAuth(globalUserId, resp);
|
|
159
|
+
}
|
|
160
|
+
return resp;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
118
163
|
getDynamicVariable(variable) {
|
|
119
164
|
return __awaiter(this, void 0, void 0, function* () {
|
|
120
165
|
let { parameters } = this;
|