@budibase/server 2.6.16-alpha.5 → 2.6.17
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/builder/assets/{index.07382a47.css → index.86c992bf.css} +2 -2
- package/builder/assets/{index.b9eeb2a8.js → index.a40dcadd.js} +315 -307
- package/builder/index.html +2 -2
- package/dist/api/controllers/datasource.js +39 -70
- package/dist/api/controllers/integration.js +2 -2
- package/dist/api/routes/datasource.js +0 -1
- package/dist/automations/steps/make.js +5 -19
- package/dist/automations/steps/zapier.js +6 -19
- package/dist/automations/triggers.js +2 -1
- package/dist/automations/utils.js +22 -17
- package/dist/db/dynamoClient.js +1 -1
- package/dist/integrations/airtable.js +2 -28
- package/dist/integrations/arangodb.js +3 -19
- package/dist/integrations/couchdb.js +1 -16
- package/dist/integrations/dynamodb.js +0 -16
- package/dist/integrations/elasticsearch.js +0 -15
- package/dist/integrations/firebase.js +0 -15
- package/dist/integrations/googlesheets.js +1 -30
- package/dist/integrations/index.js +2 -5
- package/dist/integrations/microsoftSqlServer.js +0 -16
- package/dist/integrations/mongodb.js +0 -16
- package/dist/integrations/mysql.js +5 -21
- package/dist/integrations/oracle.js +0 -29
- package/dist/integrations/postgres.js +7 -26
- package/dist/integrations/redis.js +1 -20
- package/dist/integrations/s3.js +4 -23
- package/dist/integrations/snowflake.js +0 -15
- package/dist/migrations/functions/backfill/app/queries.js +2 -1
- package/dist/sdk/app/datasources/datasources.js +3 -10
- package/dist/threads/automation.js +2 -1
- package/dist/threads/index.js +2 -2
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/jest.config.ts +3 -3
- package/nodemon.json +3 -7
- package/package.json +9 -10
- package/src/api/controllers/datasource.ts +49 -88
- package/src/api/controllers/integration.ts +3 -3
- package/src/api/routes/datasource.ts +0 -5
- package/src/automations/steps/make.ts +1 -18
- package/src/automations/steps/zapier.ts +1 -18
- package/src/automations/tests/zapier.spec.js +27 -0
- package/src/automations/triggers.ts +5 -3
- package/src/automations/utils.ts +23 -16
- package/src/db/dynamoClient.ts +1 -1
- package/src/definitions/automations.ts +1 -5
- package/src/integration-test/postgres.spec.ts +1 -0
- package/src/integrations/airtable.ts +4 -31
- package/src/integrations/arangodb.ts +2 -18
- package/src/integrations/couchdb.ts +4 -18
- package/src/integrations/dynamodb.ts +5 -34
- package/src/integrations/elasticsearch.ts +1 -16
- package/src/integrations/firebase.ts +0 -15
- package/src/integrations/googlesheets.ts +2 -31
- package/src/integrations/index.ts +7 -12
- package/src/integrations/microsoftSqlServer.ts +0 -16
- package/src/integrations/mongodb.ts +0 -16
- package/src/integrations/mysql.ts +16 -27
- package/src/integrations/oracle.ts +6 -28
- package/src/integrations/postgres.ts +3 -21
- package/src/integrations/redis.ts +3 -26
- package/src/integrations/s3.ts +3 -19
- package/src/integrations/snowflake.ts +1 -20
- package/src/migrations/functions/backfill/app/queries.ts +1 -1
- package/src/sdk/app/datasources/datasources.ts +1 -7
- package/src/threads/automation.ts +11 -6
- package/src/threads/definitions.ts +0 -2
- package/src/threads/index.ts +4 -2
- package/tsconfig.json +1 -1
- package/src/automations/tests/make.spec.ts +0 -54
- package/src/automations/tests/zapier.spec.ts +0 -56
package/jest.config.ts
CHANGED
|
@@ -20,9 +20,9 @@ const baseConfig: Config.InitialProjectOptions = {
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
// add pro sources if they exist
|
|
23
|
-
if (fs.existsSync("
|
|
24
|
-
baseConfig.moduleNameMapper
|
|
25
|
-
"<rootDir
|
|
23
|
+
if (fs.existsSync("../../../budibase-pro")) {
|
|
24
|
+
baseConfig.moduleNameMapper["@budibase/pro"] =
|
|
25
|
+
"<rootDir>/../../../budibase-pro/packages/pro/src"
|
|
26
26
|
}
|
|
27
27
|
|
|
28
28
|
const config: Config.InitialOptions = {
|
package/nodemon.json
CHANGED
|
@@ -1,10 +1,6 @@
|
|
|
1
1
|
{
|
|
2
|
-
"watch": ["src", "../backend-core", "
|
|
2
|
+
"watch": ["src", "../backend-core", "../../../budibase-pro/packages/pro"],
|
|
3
3
|
"ext": "js,ts,json",
|
|
4
|
-
"ignore": [
|
|
5
|
-
"src/**/*.spec.ts",
|
|
6
|
-
"src/**/*.spec.js",
|
|
7
|
-
"../backend-core/dist/**/*"
|
|
8
|
-
],
|
|
4
|
+
"ignore": ["src/**/*.spec.ts", "src/**/*.spec.js", "../backend-core/dist/**/*"],
|
|
9
5
|
"exec": "ts-node src/index.ts"
|
|
10
|
-
}
|
|
6
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@budibase/server",
|
|
3
3
|
"email": "hi@budibase.com",
|
|
4
|
-
"version": "2.6.
|
|
4
|
+
"version": "2.6.17",
|
|
5
5
|
"description": "Budibase Web Server",
|
|
6
6
|
"main": "src/index.ts",
|
|
7
7
|
"repository": {
|
|
@@ -45,12 +45,12 @@
|
|
|
45
45
|
"license": "GPL-3.0",
|
|
46
46
|
"dependencies": {
|
|
47
47
|
"@apidevtools/swagger-parser": "10.0.3",
|
|
48
|
-
"@budibase/backend-core": "2.6.
|
|
49
|
-
"@budibase/client": "2.6.
|
|
50
|
-
"@budibase/pro": "2.6.16
|
|
51
|
-
"@budibase/shared-core": "2.6.
|
|
52
|
-
"@budibase/string-templates": "2.6.
|
|
53
|
-
"@budibase/types": "2.6.
|
|
48
|
+
"@budibase/backend-core": "^2.6.17",
|
|
49
|
+
"@budibase/client": "^2.6.17",
|
|
50
|
+
"@budibase/pro": "2.6.16",
|
|
51
|
+
"@budibase/shared-core": "^2.6.17",
|
|
52
|
+
"@budibase/string-templates": "^2.6.17",
|
|
53
|
+
"@budibase/types": "^2.6.17",
|
|
54
54
|
"@bull-board/api": "3.7.0",
|
|
55
55
|
"@bull-board/koa": "3.9.4",
|
|
56
56
|
"@elastic/elasticsearch": "7.10.0",
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"mysql2": "2.3.3",
|
|
100
100
|
"node-fetch": "2.6.7",
|
|
101
101
|
"open": "8.4.0",
|
|
102
|
-
"pg": "8.
|
|
102
|
+
"pg": "8.5.1",
|
|
103
103
|
"posthog-node": "1.3.0",
|
|
104
104
|
"pouchdb": "7.3.0",
|
|
105
105
|
"pouchdb-adapter-memory": "7.2.2",
|
|
@@ -141,7 +141,6 @@
|
|
|
141
141
|
"@types/node": "14.18.20",
|
|
142
142
|
"@types/node-fetch": "2.6.1",
|
|
143
143
|
"@types/oracledb": "5.2.2",
|
|
144
|
-
"@types/pg": "8.6.6",
|
|
145
144
|
"@types/pouchdb": "6.4.0",
|
|
146
145
|
"@types/redis": "4.0.11",
|
|
147
146
|
"@types/server-destroy": "1.0.1",
|
|
@@ -177,5 +176,5 @@
|
|
|
177
176
|
"optionalDependencies": {
|
|
178
177
|
"oracledb": "5.3.0"
|
|
179
178
|
},
|
|
180
|
-
"gitHead": "
|
|
179
|
+
"gitHead": "2a0993fe5e3cab1ec779603cc9228f824e2cea4d"
|
|
181
180
|
}
|
|
@@ -18,71 +18,11 @@ import {
|
|
|
18
18
|
Row,
|
|
19
19
|
CreateDatasourceResponse,
|
|
20
20
|
UpdateDatasourceResponse,
|
|
21
|
+
UpdateDatasourceRequest,
|
|
21
22
|
CreateDatasourceRequest,
|
|
22
|
-
VerifyDatasourceRequest,
|
|
23
|
-
VerifyDatasourceResponse,
|
|
24
|
-
IntegrationBase,
|
|
25
|
-
DatasourcePlus,
|
|
26
23
|
} from "@budibase/types"
|
|
27
24
|
import sdk from "../../sdk"
|
|
28
25
|
|
|
29
|
-
function getErrorTables(errors: any, errorType: string) {
|
|
30
|
-
return Object.entries(errors)
|
|
31
|
-
.filter(entry => entry[1] === errorType)
|
|
32
|
-
.map(([name]) => name)
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
function updateError(error: any, newError: any, tables: string[]) {
|
|
36
|
-
if (!error) {
|
|
37
|
-
error = ""
|
|
38
|
-
}
|
|
39
|
-
if (error.length > 0) {
|
|
40
|
-
error += "\n"
|
|
41
|
-
}
|
|
42
|
-
error += `${newError} ${tables.join(", ")}`
|
|
43
|
-
return error
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
async function getConnector(
|
|
47
|
-
datasource: Datasource
|
|
48
|
-
): Promise<IntegrationBase | DatasourcePlus> {
|
|
49
|
-
const Connector = await getIntegration(datasource.source)
|
|
50
|
-
// can't enrich if it doesn't have an ID yet
|
|
51
|
-
if (datasource._id) {
|
|
52
|
-
datasource = await sdk.datasources.enrich(datasource)
|
|
53
|
-
}
|
|
54
|
-
// Connect to the DB and build the schema
|
|
55
|
-
return new Connector(datasource.config)
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function buildSchemaHelper(datasource: Datasource) {
|
|
59
|
-
const connector = (await getConnector(datasource)) as DatasourcePlus
|
|
60
|
-
await connector.buildSchema(datasource._id!, datasource.entities!)
|
|
61
|
-
|
|
62
|
-
const errors = connector.schemaErrors
|
|
63
|
-
let error = null
|
|
64
|
-
if (errors && Object.keys(errors).length > 0) {
|
|
65
|
-
const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY)
|
|
66
|
-
const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN)
|
|
67
|
-
if (noKey.length) {
|
|
68
|
-
error = updateError(
|
|
69
|
-
error,
|
|
70
|
-
"No primary key constraint found for the following:",
|
|
71
|
-
noKey
|
|
72
|
-
)
|
|
73
|
-
}
|
|
74
|
-
if (invalidCol.length) {
|
|
75
|
-
const invalidCols = Object.values(InvalidColumns).join(", ")
|
|
76
|
-
error = updateError(
|
|
77
|
-
error,
|
|
78
|
-
`Cannot use columns ${invalidCols} found in following:`,
|
|
79
|
-
invalidCol
|
|
80
|
-
)
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
return { tables: connector.tables, error }
|
|
84
|
-
}
|
|
85
|
-
|
|
86
26
|
export async function fetch(ctx: UserCtx) {
|
|
87
27
|
// Get internal tables
|
|
88
28
|
const db = context.getAppDB()
|
|
@@ -126,33 +66,6 @@ export async function fetch(ctx: UserCtx) {
|
|
|
126
66
|
ctx.body = [bbInternalDb, ...datasources]
|
|
127
67
|
}
|
|
128
68
|
|
|
129
|
-
export async function verify(
|
|
130
|
-
ctx: UserCtx<VerifyDatasourceRequest, VerifyDatasourceResponse>
|
|
131
|
-
) {
|
|
132
|
-
const { datasource } = ctx.request.body
|
|
133
|
-
let existingDatasource: undefined | Datasource
|
|
134
|
-
if (datasource._id) {
|
|
135
|
-
existingDatasource = await sdk.datasources.get(datasource._id)
|
|
136
|
-
}
|
|
137
|
-
let enrichedDatasource = datasource
|
|
138
|
-
if (existingDatasource) {
|
|
139
|
-
enrichedDatasource = sdk.datasources.mergeConfigs(
|
|
140
|
-
datasource,
|
|
141
|
-
existingDatasource
|
|
142
|
-
)
|
|
143
|
-
}
|
|
144
|
-
const connector = await getConnector(enrichedDatasource)
|
|
145
|
-
if (!connector.testConnection) {
|
|
146
|
-
ctx.throw(400, "Connection information verification not supported")
|
|
147
|
-
}
|
|
148
|
-
const response = await connector.testConnection()
|
|
149
|
-
|
|
150
|
-
ctx.body = {
|
|
151
|
-
connected: response.connected,
|
|
152
|
-
error: response.error,
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
|
|
156
69
|
export async function buildSchemaFromDb(ctx: UserCtx) {
|
|
157
70
|
const db = context.getAppDB()
|
|
158
71
|
const datasource = await sdk.datasources.get(ctx.params.datasourceId)
|
|
@@ -398,3 +311,51 @@ export async function query(ctx: UserCtx) {
|
|
|
398
311
|
ctx.throw(400, err)
|
|
399
312
|
}
|
|
400
313
|
}
|
|
314
|
+
|
|
315
|
+
function getErrorTables(errors: any, errorType: string) {
|
|
316
|
+
return Object.entries(errors)
|
|
317
|
+
.filter(entry => entry[1] === errorType)
|
|
318
|
+
.map(([name]) => name)
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function updateError(error: any, newError: any, tables: string[]) {
|
|
322
|
+
if (!error) {
|
|
323
|
+
error = ""
|
|
324
|
+
}
|
|
325
|
+
if (error.length > 0) {
|
|
326
|
+
error += "\n"
|
|
327
|
+
}
|
|
328
|
+
error += `${newError} ${tables.join(", ")}`
|
|
329
|
+
return error
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
async function buildSchemaHelper(datasource: Datasource) {
|
|
333
|
+
const Connector = await getIntegration(datasource.source)
|
|
334
|
+
datasource = await sdk.datasources.enrich(datasource)
|
|
335
|
+
// Connect to the DB and build the schema
|
|
336
|
+
const connector = new Connector(datasource.config)
|
|
337
|
+
await connector.buildSchema(datasource._id, datasource.entities)
|
|
338
|
+
|
|
339
|
+
const errors = connector.schemaErrors
|
|
340
|
+
let error = null
|
|
341
|
+
if (errors && Object.keys(errors).length > 0) {
|
|
342
|
+
const noKey = getErrorTables(errors, BuildSchemaErrors.NO_KEY)
|
|
343
|
+
const invalidCol = getErrorTables(errors, BuildSchemaErrors.INVALID_COLUMN)
|
|
344
|
+
if (noKey.length) {
|
|
345
|
+
error = updateError(
|
|
346
|
+
error,
|
|
347
|
+
"No primary key constraint found for the following:",
|
|
348
|
+
noKey
|
|
349
|
+
)
|
|
350
|
+
}
|
|
351
|
+
if (invalidCol.length) {
|
|
352
|
+
const invalidCols = Object.values(InvalidColumns).join(", ")
|
|
353
|
+
error = updateError(
|
|
354
|
+
error,
|
|
355
|
+
`Cannot use columns ${invalidCols} found in following:`,
|
|
356
|
+
invalidCol
|
|
357
|
+
)
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
return { tables: connector.tables, error }
|
|
361
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getDefinitions } from "../../integrations"
|
|
2
2
|
import { BBContext } from "@budibase/types"
|
|
3
3
|
|
|
4
4
|
export async function fetch(ctx: BBContext) {
|
|
@@ -7,7 +7,7 @@ export async function fetch(ctx: BBContext) {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
export async function find(ctx: BBContext) {
|
|
10
|
-
const
|
|
11
|
-
ctx.body = def
|
|
10
|
+
const defs = await getDefinitions()
|
|
12
11
|
ctx.status = 200
|
|
12
|
+
ctx.body = defs[ctx.params.type]
|
|
13
13
|
}
|
|
@@ -26,10 +26,6 @@ export const definition: AutomationStepSchema = {
|
|
|
26
26
|
type: AutomationIOType.STRING,
|
|
27
27
|
title: "Webhook URL",
|
|
28
28
|
},
|
|
29
|
-
body: {
|
|
30
|
-
type: AutomationIOType.JSON,
|
|
31
|
-
title: "Payload",
|
|
32
|
-
},
|
|
33
29
|
value1: {
|
|
34
30
|
type: AutomationIOType.STRING,
|
|
35
31
|
title: "Input Value 1",
|
|
@@ -74,19 +70,7 @@ export const definition: AutomationStepSchema = {
|
|
|
74
70
|
}
|
|
75
71
|
|
|
76
72
|
export async function run({ inputs }: AutomationStepInput) {
|
|
77
|
-
|
|
78
|
-
const { url, value1, value2, value3, value4, value5, body } = inputs
|
|
79
|
-
|
|
80
|
-
let payload = {}
|
|
81
|
-
try {
|
|
82
|
-
payload = body?.value ? JSON.parse(body?.value) : {}
|
|
83
|
-
} catch (err) {
|
|
84
|
-
return {
|
|
85
|
-
httpStatus: 400,
|
|
86
|
-
response: "Invalid payload JSON",
|
|
87
|
-
success: false,
|
|
88
|
-
}
|
|
89
|
-
}
|
|
73
|
+
const { url, value1, value2, value3, value4, value5 } = inputs
|
|
90
74
|
|
|
91
75
|
if (!url?.trim()?.length) {
|
|
92
76
|
return {
|
|
@@ -105,7 +89,6 @@ export async function run({ inputs }: AutomationStepInput) {
|
|
|
105
89
|
value3,
|
|
106
90
|
value4,
|
|
107
91
|
value5,
|
|
108
|
-
...payload,
|
|
109
92
|
}),
|
|
110
93
|
headers: {
|
|
111
94
|
"Content-Type": "application/json",
|
|
@@ -24,10 +24,6 @@ export const definition: AutomationStepSchema = {
|
|
|
24
24
|
type: AutomationIOType.STRING,
|
|
25
25
|
title: "Webhook URL",
|
|
26
26
|
},
|
|
27
|
-
body: {
|
|
28
|
-
type: AutomationIOType.JSON,
|
|
29
|
-
title: "Payload",
|
|
30
|
-
},
|
|
31
27
|
value1: {
|
|
32
28
|
type: AutomationIOType.STRING,
|
|
33
29
|
title: "Payload Value 1",
|
|
@@ -67,19 +63,7 @@ export const definition: AutomationStepSchema = {
|
|
|
67
63
|
}
|
|
68
64
|
|
|
69
65
|
export async function run({ inputs }: AutomationStepInput) {
|
|
70
|
-
|
|
71
|
-
const { url, value1, value2, value3, value4, value5, body } = inputs
|
|
72
|
-
|
|
73
|
-
let payload = {}
|
|
74
|
-
try {
|
|
75
|
-
payload = body?.value ? JSON.parse(body?.value) : {}
|
|
76
|
-
} catch (err) {
|
|
77
|
-
return {
|
|
78
|
-
httpStatus: 400,
|
|
79
|
-
response: "Invalid payload JSON",
|
|
80
|
-
success: false,
|
|
81
|
-
}
|
|
82
|
-
}
|
|
66
|
+
const { url, value1, value2, value3, value4, value5 } = inputs
|
|
83
67
|
|
|
84
68
|
if (!url?.trim()?.length) {
|
|
85
69
|
return {
|
|
@@ -101,7 +85,6 @@ export async function run({ inputs }: AutomationStepInput) {
|
|
|
101
85
|
value3,
|
|
102
86
|
value4,
|
|
103
87
|
value5,
|
|
104
|
-
...payload,
|
|
105
88
|
}),
|
|
106
89
|
headers: {
|
|
107
90
|
"Content-Type": "application/json",
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
const setup = require("./utilities")
|
|
2
|
+
const fetch = require("node-fetch")
|
|
3
|
+
|
|
4
|
+
jest.mock("node-fetch")
|
|
5
|
+
|
|
6
|
+
describe("test the outgoing webhook action", () => {
|
|
7
|
+
let inputs
|
|
8
|
+
let config = setup.getConfig()
|
|
9
|
+
|
|
10
|
+
beforeAll(async () => {
|
|
11
|
+
await config.init()
|
|
12
|
+
inputs = {
|
|
13
|
+
value1: "test",
|
|
14
|
+
url: "http://www.test.com",
|
|
15
|
+
}
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
afterAll(setup.afterAll)
|
|
19
|
+
|
|
20
|
+
it("should be able to run the action", async () => {
|
|
21
|
+
const res = await setup.runStep(setup.actions.zapier.stepId, inputs)
|
|
22
|
+
expect(res.response.url).toEqual("http://www.test.com")
|
|
23
|
+
expect(res.response.method).toEqual("post")
|
|
24
|
+
expect(res.success).toEqual(true)
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
})
|
|
@@ -9,7 +9,7 @@ import { checkTestFlag } from "../utilities/redis"
|
|
|
9
9
|
import * as utils from "./utils"
|
|
10
10
|
import env from "../environment"
|
|
11
11
|
import { context, db as dbCore } from "@budibase/backend-core"
|
|
12
|
-
import { Automation, Row } from "@budibase/types"
|
|
12
|
+
import { Automation, Row, AutomationData, AutomationJob } from "@budibase/types"
|
|
13
13
|
|
|
14
14
|
export const TRIGGER_DEFINITIONS = definitions
|
|
15
15
|
const JOB_OPTS = {
|
|
@@ -109,14 +109,16 @@ export async function externalTrigger(
|
|
|
109
109
|
}
|
|
110
110
|
params.fields = coercedFields
|
|
111
111
|
}
|
|
112
|
-
|
|
112
|
+
|
|
113
|
+
const data: AutomationData = { automation, event: params as any }
|
|
113
114
|
if (getResponses) {
|
|
114
115
|
data.event = {
|
|
115
116
|
...data.event,
|
|
116
117
|
appId: context.getAppId(),
|
|
117
118
|
automation,
|
|
118
119
|
}
|
|
119
|
-
|
|
120
|
+
const job = { data } as AutomationJob
|
|
121
|
+
return utils.processEvent(job)
|
|
120
122
|
} else {
|
|
121
123
|
return automationQueue.add(data, JOB_OPTS)
|
|
122
124
|
}
|
package/src/automations/utils.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { db as dbCore, context } from "@budibase/backend-core"
|
|
|
8
8
|
import { getAutomationMetadataParams } from "../db/utils"
|
|
9
9
|
import { cloneDeep } from "lodash/fp"
|
|
10
10
|
import { quotas } from "@budibase/pro"
|
|
11
|
-
import { Automation, WebhookActionType } from "@budibase/types"
|
|
11
|
+
import { Automation, AutomationJob, WebhookActionType } from "@budibase/types"
|
|
12
12
|
import sdk from "../sdk"
|
|
13
13
|
|
|
14
14
|
const REBOOT_CRON = "@reboot"
|
|
@@ -16,27 +16,34 @@ const WH_STEP_ID = definitions.WEBHOOK.stepId
|
|
|
16
16
|
const CRON_STEP_ID = definitions.CRON.stepId
|
|
17
17
|
const Runner = new Thread(ThreadType.AUTOMATION)
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
return
|
|
19
|
+
function loggingArgs(job: AutomationJob) {
|
|
20
|
+
return {
|
|
21
|
+
jobId: job.id,
|
|
22
|
+
trigger: job.data.automation.definition.trigger.event,
|
|
23
|
+
}
|
|
21
24
|
}
|
|
22
25
|
|
|
23
|
-
export async function processEvent(job:
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
export async function processEvent(job: AutomationJob) {
|
|
27
|
+
const appId = job.data.event.appId!
|
|
28
|
+
const automationId = job.data.automation._id!
|
|
29
|
+
const task = async () => {
|
|
30
|
+
try {
|
|
31
|
+
// need to actually await these so that an error can be captured properly
|
|
32
|
+
console.log("automation running", loggingArgs(job))
|
|
33
|
+
|
|
29
34
|
const runFn = () => Runner.run(job)
|
|
30
|
-
|
|
35
|
+
const result = await quotas.addAutomation(runFn, {
|
|
31
36
|
automationId,
|
|
32
37
|
})
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
38
|
+
console.log("automation completed", loggingArgs(job))
|
|
39
|
+
return result
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.error(`automation was unable to run`, err, loggingArgs(job))
|
|
42
|
+
return { err }
|
|
43
|
+
}
|
|
39
44
|
}
|
|
45
|
+
|
|
46
|
+
return await context.doInAutomationContext({ appId, automationId, task })
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
export async function updateTestHistory(
|
package/src/db/dynamoClient.ts
CHANGED
|
@@ -140,7 +140,7 @@ export function init(endpoint: string) {
|
|
|
140
140
|
docClient = new AWS.DynamoDB.DocumentClient(docClientParams)
|
|
141
141
|
}
|
|
142
142
|
|
|
143
|
-
if (!env.isProd()
|
|
143
|
+
if (!env.isProd()) {
|
|
144
144
|
env._set("AWS_ACCESS_KEY_ID", "KEY_ID")
|
|
145
145
|
env._set("AWS_SECRET_ACCESS_KEY", "SECRET_KEY")
|
|
146
146
|
init("http://localhost:8333")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { AutomationResults, AutomationStep
|
|
1
|
+
import { AutomationResults, AutomationStep } from "@budibase/types"
|
|
2
2
|
|
|
3
3
|
export enum LoopStepType {
|
|
4
4
|
ARRAY = "Array",
|
|
@@ -27,7 +27,3 @@ export interface AutomationContext extends AutomationResults {
|
|
|
27
27
|
env?: Record<string, string>
|
|
28
28
|
trigger: any
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
export interface AutomationMetadata extends Document {
|
|
32
|
-
errorCount?: number
|
|
33
|
-
}
|
|
@@ -19,6 +19,7 @@ import _ from "lodash"
|
|
|
19
19
|
import { generator } from "@budibase/backend-core/tests"
|
|
20
20
|
import { utils } from "@budibase/backend-core"
|
|
21
21
|
import { GenericContainer } from "testcontainers"
|
|
22
|
+
import { generateRowIdField } from "../integrations/utils"
|
|
22
23
|
|
|
23
24
|
const config = setup.getConfig()!
|
|
24
25
|
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ConnectionInfo,
|
|
3
|
-
DatasourceFeature,
|
|
4
|
-
DatasourceFieldType,
|
|
5
2
|
Integration,
|
|
6
|
-
|
|
3
|
+
DatasourceFieldType,
|
|
7
4
|
QueryType,
|
|
5
|
+
IntegrationBase,
|
|
8
6
|
} from "@budibase/types"
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
const Airtable = require("airtable")
|
|
11
9
|
|
|
12
10
|
interface AirtableConfig {
|
|
13
11
|
apiKey: string
|
|
@@ -20,7 +18,6 @@ const SCHEMA: Integration = {
|
|
|
20
18
|
"Airtable is a spreadsheet-database hybrid, with the features of a database but applied to a spreadsheet.",
|
|
21
19
|
friendlyName: "Airtable",
|
|
22
20
|
type: "Spreadsheet",
|
|
23
|
-
features: [DatasourceFeature.CONNECTION_CHECKING],
|
|
24
21
|
datasource: {
|
|
25
22
|
apiKey: {
|
|
26
23
|
type: DatasourceFieldType.PASSWORD,
|
|
@@ -84,37 +81,13 @@ const SCHEMA: Integration = {
|
|
|
84
81
|
|
|
85
82
|
class AirtableIntegration implements IntegrationBase {
|
|
86
83
|
private config: AirtableConfig
|
|
87
|
-
private client
|
|
84
|
+
private client: any
|
|
88
85
|
|
|
89
86
|
constructor(config: AirtableConfig) {
|
|
90
87
|
this.config = config
|
|
91
88
|
this.client = new Airtable(config).base(config.base)
|
|
92
89
|
}
|
|
93
90
|
|
|
94
|
-
async testConnection(): Promise<ConnectionInfo> {
|
|
95
|
-
const mockTable = Date.now().toString()
|
|
96
|
-
try {
|
|
97
|
-
await this.client.makeRequest({
|
|
98
|
-
path: `/${mockTable}`,
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
return { connected: true }
|
|
102
|
-
} catch (e: any) {
|
|
103
|
-
if (
|
|
104
|
-
e.message ===
|
|
105
|
-
`Could not find table ${mockTable} in application ${this.config.base}`
|
|
106
|
-
) {
|
|
107
|
-
// The request managed to check the application, so the credentials are valid
|
|
108
|
-
return { connected: true }
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return {
|
|
112
|
-
connected: false,
|
|
113
|
-
error: e.message as string,
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
91
|
async create(query: { table: any; json: any }) {
|
|
119
92
|
const { table, json } = query
|
|
120
93
|
|
|
@@ -3,11 +3,9 @@ import {
|
|
|
3
3
|
DatasourceFieldType,
|
|
4
4
|
QueryType,
|
|
5
5
|
IntegrationBase,
|
|
6
|
-
DatasourceFeature,
|
|
7
|
-
ConnectionInfo,
|
|
8
6
|
} from "@budibase/types"
|
|
9
7
|
|
|
10
|
-
|
|
8
|
+
const { Database, aql } = require("arangojs")
|
|
11
9
|
|
|
12
10
|
interface ArangodbConfig {
|
|
13
11
|
url: string
|
|
@@ -23,7 +21,6 @@ const SCHEMA: Integration = {
|
|
|
23
21
|
type: "Non-relational",
|
|
24
22
|
description:
|
|
25
23
|
"ArangoDB is a scalable open-source multi-model database natively supporting graph, document and search. All supported data models & access patterns can be combined in queries allowing for maximal flexibility. ",
|
|
26
|
-
features: [DatasourceFeature.CONNECTION_CHECKING],
|
|
27
24
|
datasource: {
|
|
28
25
|
url: {
|
|
29
26
|
type: DatasourceFieldType.STRING,
|
|
@@ -61,7 +58,7 @@ const SCHEMA: Integration = {
|
|
|
61
58
|
|
|
62
59
|
class ArangoDBIntegration implements IntegrationBase {
|
|
63
60
|
private config: ArangodbConfig
|
|
64
|
-
private client
|
|
61
|
+
private client: any
|
|
65
62
|
|
|
66
63
|
constructor(config: ArangodbConfig) {
|
|
67
64
|
const newConfig = {
|
|
@@ -77,19 +74,6 @@ class ArangoDBIntegration implements IntegrationBase {
|
|
|
77
74
|
this.client = new Database(newConfig)
|
|
78
75
|
}
|
|
79
76
|
|
|
80
|
-
async testConnection() {
|
|
81
|
-
const response: ConnectionInfo = {
|
|
82
|
-
connected: false,
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
await this.client.get()
|
|
86
|
-
response.connected = true
|
|
87
|
-
} catch (e: any) {
|
|
88
|
-
response.error = e.message as string
|
|
89
|
-
}
|
|
90
|
-
return response
|
|
91
|
-
}
|
|
92
|
-
|
|
93
77
|
async read(query: { sql: any }) {
|
|
94
78
|
try {
|
|
95
79
|
const result = await this.client.query(query.sql)
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import {
|
|
2
|
-
ConnectionInfo,
|
|
3
|
-
DatasourceFeature,
|
|
4
2
|
DatasourceFieldType,
|
|
5
3
|
Document,
|
|
6
4
|
Integration,
|
|
@@ -20,7 +18,6 @@ const SCHEMA: Integration = {
|
|
|
20
18
|
type: "Non-relational",
|
|
21
19
|
description:
|
|
22
20
|
"Apache CouchDB is an open-source document-oriented NoSQL database, implemented in Erlang.",
|
|
23
|
-
features: [DatasourceFeature.CONNECTION_CHECKING],
|
|
24
21
|
datasource: {
|
|
25
22
|
url: {
|
|
26
23
|
type: DatasourceFieldType.STRING,
|
|
@@ -64,32 +61,21 @@ const SCHEMA: Integration = {
|
|
|
64
61
|
}
|
|
65
62
|
|
|
66
63
|
class CouchDBIntegration implements IntegrationBase {
|
|
67
|
-
private
|
|
64
|
+
private config: CouchDBConfig
|
|
65
|
+
private readonly client: any
|
|
68
66
|
|
|
69
67
|
constructor(config: CouchDBConfig) {
|
|
68
|
+
this.config = config
|
|
70
69
|
this.client = dbCore.DatabaseWithConnection(config.database, config.url)
|
|
71
70
|
}
|
|
72
71
|
|
|
73
|
-
async testConnection() {
|
|
74
|
-
const response: ConnectionInfo = {
|
|
75
|
-
connected: false,
|
|
76
|
-
}
|
|
77
|
-
try {
|
|
78
|
-
const result = await this.query("exists", "validation error", {})
|
|
79
|
-
response.connected = result === true
|
|
80
|
-
} catch (e: any) {
|
|
81
|
-
response.error = e.message as string
|
|
82
|
-
}
|
|
83
|
-
return response
|
|
84
|
-
}
|
|
85
|
-
|
|
86
72
|
async query(
|
|
87
73
|
command: string,
|
|
88
74
|
errorMsg: string,
|
|
89
75
|
query: { json?: object; id?: string }
|
|
90
76
|
) {
|
|
91
77
|
try {
|
|
92
|
-
return await
|
|
78
|
+
return await this.client[command](query.id || query.json)
|
|
93
79
|
} catch (err) {
|
|
94
80
|
console.error(errorMsg, err)
|
|
95
81
|
throw err
|