Merge branch 'develop' into chore/pro_as_submodule
This commit is contained in:
commit
98b372965c
|
@ -58,6 +58,7 @@ jobs:
|
||||||
node-version: 14.x
|
node-version: 14.x
|
||||||
- run: yarn
|
- run: yarn
|
||||||
- run: yarn bootstrap
|
- run: yarn bootstrap
|
||||||
|
- run: yarn build
|
||||||
- run: yarn test --ignore=@budibase/pro
|
- run: yarn test --ignore=@budibase/pro
|
||||||
- uses: codecov/codecov-action@v3
|
- uses: codecov/codecov-action@v3
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/backend-core",
|
"packages/backend-core",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "dist/src/index.js",
|
"main": "dist/src/index.js",
|
||||||
"types": "dist/src/index.d.ts",
|
"types": "dist/src/index.d.ts",
|
||||||
|
@ -22,7 +22,7 @@
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/nano": "10.1.2",
|
"@budibase/nano": "10.1.2",
|
||||||
"@budibase/pouchdb-replication-stream": "1.2.10",
|
"@budibase/pouchdb-replication-stream": "1.2.10",
|
||||||
"@budibase/types": "2.5.6-alpha.3",
|
"@budibase/types": "2.5.6-alpha.5",
|
||||||
"@shopify/jest-koa-mocks": "5.0.1",
|
"@shopify/jest-koa-mocks": "5.0.1",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
"aws-cloudfront-sign": "2.2.0",
|
"aws-cloudfront-sign": "2.2.0",
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export * as correlation from "./correlation/correlation"
|
export * as correlation from "./correlation/correlation"
|
||||||
export { default as logger } from "./pino/logger"
|
export { logger, disableLogger } from "./pino/logger"
|
||||||
export * from "./alerts"
|
export * from "./alerts"
|
||||||
|
|
||||||
// turn off or on context logging i.e. tenantId, appId etc
|
// turn off or on context logging i.e. tenantId, appId etc
|
||||||
|
|
|
@ -5,6 +5,17 @@ import * as correlation from "../correlation"
|
||||||
import { IdentityType } from "@budibase/types"
|
import { IdentityType } from "@budibase/types"
|
||||||
import { LOG_CONTEXT } from "../index"
|
import { LOG_CONTEXT } from "../index"
|
||||||
|
|
||||||
|
// CORE LOGGERS - for disabling
|
||||||
|
|
||||||
|
const BUILT_INS = {
|
||||||
|
log: console.log,
|
||||||
|
error: console.error,
|
||||||
|
info: console.info,
|
||||||
|
warn: console.warn,
|
||||||
|
trace: console.trace,
|
||||||
|
debug: console.debug,
|
||||||
|
}
|
||||||
|
|
||||||
// LOGGER
|
// LOGGER
|
||||||
|
|
||||||
const pinoOptions: LoggerOptions = {
|
const pinoOptions: LoggerOptions = {
|
||||||
|
@ -31,6 +42,15 @@ if (env.isDev()) {
|
||||||
|
|
||||||
export const logger = pino(pinoOptions)
|
export const logger = pino(pinoOptions)
|
||||||
|
|
||||||
|
export function disableLogger() {
|
||||||
|
console.log = BUILT_INS.log
|
||||||
|
console.error = BUILT_INS.error
|
||||||
|
console.info = BUILT_INS.info
|
||||||
|
console.warn = BUILT_INS.warn
|
||||||
|
console.trace = BUILT_INS.trace
|
||||||
|
console.debug = BUILT_INS.debug
|
||||||
|
}
|
||||||
|
|
||||||
// CONSOLE OVERRIDES
|
// CONSOLE OVERRIDES
|
||||||
|
|
||||||
interface MergingObject {
|
interface MergingObject {
|
||||||
|
@ -166,5 +186,3 @@ const getIdentity = () => {
|
||||||
}
|
}
|
||||||
return identity
|
return identity
|
||||||
}
|
}
|
||||||
|
|
||||||
export default logger
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import env from "../../environment"
|
import env from "../../environment"
|
||||||
import logger from "./logger"
|
import { logger } from "./logger"
|
||||||
import { IncomingMessage } from "http"
|
import { IncomingMessage } from "http"
|
||||||
const pino = require("koa-pino-logger")
|
const pino = require("koa-pino-logger")
|
||||||
import { Options } from "pino-http"
|
import { Options } from "pino-http"
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
import { validate } from "../utils"
|
||||||
|
import fetch from "node-fetch"
|
||||||
|
import { PluginType } from "@budibase/types"
|
||||||
|
|
||||||
|
const repoUrl =
|
||||||
|
"https://raw.githubusercontent.com/Budibase/budibase-skeleton/master"
|
||||||
|
const automationLink = `${repoUrl}/automation/schema.json.hbs`
|
||||||
|
const componentLink = `${repoUrl}/component/schema.json.hbs`
|
||||||
|
const datasourceLink = `${repoUrl}/datasource/schema.json.hbs`
|
||||||
|
|
||||||
|
async function getSchema(link: string) {
|
||||||
|
const response = await fetch(link)
|
||||||
|
if (response.status > 300) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
const text = await response.text()
|
||||||
|
return JSON.parse(text)
|
||||||
|
}
|
||||||
|
|
||||||
|
async function runTest(opts: { link?: string; schema?: any }) {
|
||||||
|
let error
|
||||||
|
try {
|
||||||
|
let schema = opts.schema
|
||||||
|
if (opts.link) {
|
||||||
|
schema = await getSchema(opts.link)
|
||||||
|
}
|
||||||
|
validate(schema)
|
||||||
|
} catch (err) {
|
||||||
|
error = err
|
||||||
|
}
|
||||||
|
return error
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("it should be able to validate an automation schema", () => {
|
||||||
|
it("should return automation skeleton schema is valid", async () => {
|
||||||
|
const error = await runTest({ link: automationLink })
|
||||||
|
expect(error).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should fail given invalid automation schema", async () => {
|
||||||
|
const error = await runTest({
|
||||||
|
schema: {
|
||||||
|
type: PluginType.AUTOMATION,
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(error).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("it should be able to validate a component schema", () => {
|
||||||
|
it("should return component skeleton schema is valid", async () => {
|
||||||
|
const error = await runTest({ link: componentLink })
|
||||||
|
expect(error).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should fail given invalid component schema", async () => {
|
||||||
|
const error = await runTest({
|
||||||
|
schema: {
|
||||||
|
type: PluginType.COMPONENT,
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(error).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("it should be able to validate a datasource schema", () => {
|
||||||
|
it("should return datasource skeleton schema is valid", async () => {
|
||||||
|
const error = await runTest({ link: datasourceLink })
|
||||||
|
expect(error).toBeUndefined()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("should fail given invalid datasource schema", async () => {
|
||||||
|
const error = await runTest({
|
||||||
|
schema: {
|
||||||
|
type: PluginType.DATASOURCE,
|
||||||
|
schema: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
expect(error).toBeDefined()
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,4 +1,12 @@
|
||||||
import { DatasourceFieldType, QueryType, PluginType } from "@budibase/types"
|
import {
|
||||||
|
DatasourceFieldType,
|
||||||
|
QueryType,
|
||||||
|
PluginType,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationStepIdArray,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationCustomIOType,
|
||||||
|
} from "@budibase/types"
|
||||||
import joi from "joi"
|
import joi from "joi"
|
||||||
|
|
||||||
const DATASOURCE_TYPES = [
|
const DATASOURCE_TYPES = [
|
||||||
|
@ -19,7 +27,7 @@ function runJoi(validator: joi.Schema, schema: any) {
|
||||||
|
|
||||||
function validateComponent(schema: any) {
|
function validateComponent(schema: any) {
|
||||||
const validator = joi.object({
|
const validator = joi.object({
|
||||||
type: joi.string().allow("component").required(),
|
type: joi.string().allow(PluginType.COMPONENT).required(),
|
||||||
metadata: joi.object().unknown(true).required(),
|
metadata: joi.object().unknown(true).required(),
|
||||||
hash: joi.string().optional(),
|
hash: joi.string().optional(),
|
||||||
version: joi.string().optional(),
|
version: joi.string().optional(),
|
||||||
|
@ -53,7 +61,7 @@ function validateDatasource(schema: any) {
|
||||||
.required()
|
.required()
|
||||||
|
|
||||||
const validator = joi.object({
|
const validator = joi.object({
|
||||||
type: joi.string().allow("datasource").required(),
|
type: joi.string().allow(PluginType.DATASOURCE).required(),
|
||||||
metadata: joi.object().unknown(true).required(),
|
metadata: joi.object().unknown(true).required(),
|
||||||
hash: joi.string().optional(),
|
hash: joi.string().optional(),
|
||||||
version: joi.string().optional(),
|
version: joi.string().optional(),
|
||||||
|
@ -82,6 +90,55 @@ function validateDatasource(schema: any) {
|
||||||
runJoi(validator, schema)
|
runJoi(validator, schema)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function validateAutomation(schema: any) {
|
||||||
|
const basePropsValidator = joi.object().pattern(joi.string(), {
|
||||||
|
type: joi
|
||||||
|
.string()
|
||||||
|
.allow(...Object.values(AutomationIOType))
|
||||||
|
.required(),
|
||||||
|
customType: joi.string().allow(...Object.values(AutomationCustomIOType)),
|
||||||
|
title: joi.string(),
|
||||||
|
description: joi.string(),
|
||||||
|
enum: joi.array().items(joi.string()),
|
||||||
|
pretty: joi.array().items(joi.string()),
|
||||||
|
})
|
||||||
|
const stepSchemaValidator = joi
|
||||||
|
.object({
|
||||||
|
properties: basePropsValidator,
|
||||||
|
required: joi.array().items(joi.string()),
|
||||||
|
})
|
||||||
|
.concat(basePropsValidator)
|
||||||
|
.required()
|
||||||
|
const validator = joi.object({
|
||||||
|
type: joi.string().allow(PluginType.AUTOMATION).required(),
|
||||||
|
metadata: joi.object().unknown(true).required(),
|
||||||
|
hash: joi.string().optional(),
|
||||||
|
version: joi.string().optional(),
|
||||||
|
schema: joi.object({
|
||||||
|
name: joi.string().required(),
|
||||||
|
tagline: joi.string().required(),
|
||||||
|
icon: joi.string().required(),
|
||||||
|
description: joi.string().required(),
|
||||||
|
type: joi
|
||||||
|
.string()
|
||||||
|
.allow(AutomationStepType.ACTION, AutomationStepType.LOGIC)
|
||||||
|
.required(),
|
||||||
|
stepId: joi
|
||||||
|
.string()
|
||||||
|
.disallow(...AutomationStepIdArray)
|
||||||
|
.required(),
|
||||||
|
inputs: joi.object().optional(),
|
||||||
|
schema: joi
|
||||||
|
.object({
|
||||||
|
inputs: stepSchemaValidator,
|
||||||
|
outputs: stepSchemaValidator,
|
||||||
|
})
|
||||||
|
.required(),
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
runJoi(validator, schema)
|
||||||
|
}
|
||||||
|
|
||||||
export function validate(schema: any) {
|
export function validate(schema: any) {
|
||||||
switch (schema?.type) {
|
switch (schema?.type) {
|
||||||
case PluginType.COMPONENT:
|
case PluginType.COMPONENT:
|
||||||
|
@ -90,6 +147,9 @@ export function validate(schema: any) {
|
||||||
case PluginType.DATASOURCE:
|
case PluginType.DATASOURCE:
|
||||||
validateDatasource(schema)
|
validateDatasource(schema)
|
||||||
break
|
break
|
||||||
|
case PluginType.AUTOMATION:
|
||||||
|
validateAutomation(schema)
|
||||||
|
break
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unknown plugin type - check schema.json: ${schema.type}`)
|
throw new Error(`Unknown plugin type - check schema.json: ${schema.type}`)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
const mockFetch = jest.fn((url: any, opts: any) => {
|
const mockFetch = jest.fn((url: any, opts: any) => {
|
||||||
const fetch = jest.requireActual("node-fetch")
|
const fetch = jest.requireActual("node-fetch")
|
||||||
const env = jest.requireActual("../../../../src/environment").default
|
const env = jest.requireActual("../../../../src/environment").default
|
||||||
if (url.includes(env.COUCH_DB_URL)) {
|
if (url.includes(env.COUCH_DB_URL) || url.includes("raw.github")) {
|
||||||
return fetch(url, opts)
|
return fetch(url, opts)
|
||||||
}
|
}
|
||||||
return undefined
|
return undefined
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,8 +38,8 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "1.2.1",
|
||||||
"@budibase/shared-core": "2.5.6-alpha.3",
|
"@budibase/shared-core": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@spectrum-css/accordion": "3.0.24",
|
"@spectrum-css/accordion": "3.0.24",
|
||||||
"@spectrum-css/actionbutton": "1.0.1",
|
"@spectrum-css/actionbutton": "1.0.1",
|
||||||
"@spectrum-css/actiongroup": "1.0.1",
|
"@spectrum-css/actiongroup": "1.0.1",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
<TooltipWrapper {tooltip} {size}>
|
<TooltipWrapper {tooltip} {size}>
|
||||||
<label
|
<label
|
||||||
|
data-testid="label"
|
||||||
class:muted
|
class:muted
|
||||||
for=""
|
for=""
|
||||||
class={`spectrum-FieldLabel spectrum-FieldLabel--size${size}`}
|
class={`spectrum-FieldLabel spectrum-FieldLabel--size${size}`}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<p
|
<p
|
||||||
|
data-testid="typography-body"
|
||||||
style={`
|
style={`
|
||||||
${weight ? `font-weight:${weight};` : ""}
|
${weight ? `font-weight:${weight};` : ""}
|
||||||
${textAlign ? `text-align:${textAlign};` : ""}
|
${textAlign ? `text-align:${textAlign};` : ""}
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1
|
<h1
|
||||||
|
data-testid="typography-heading"
|
||||||
style={textAlign ? `text-align:${textAlign}` : ``}
|
style={textAlign ? `text-align:${textAlign}` : ``}
|
||||||
class:noPadding
|
class:noPadding
|
||||||
class="spectrum-Heading spectrum-Heading--size{size} spectrum-Heading--{weight}"
|
class="spectrum-Heading spectrum-Heading--size{size} spectrum-Heading--{weight}"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -9,7 +9,7 @@
|
||||||
"dev:builder": "routify -c dev:vite",
|
"dev:builder": "routify -c dev:vite",
|
||||||
"dev:vite": "vite --host 0.0.0.0",
|
"dev:vite": "vite --host 0.0.0.0",
|
||||||
"rollup": "rollup -c -w",
|
"rollup": "rollup -c -w",
|
||||||
"test": "jest"
|
"test": "vitest"
|
||||||
},
|
},
|
||||||
"jest": {
|
"jest": {
|
||||||
"globals": {
|
"globals": {
|
||||||
|
@ -58,11 +58,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.5.6-alpha.3",
|
"@budibase/bbui": "2.5.6-alpha.5",
|
||||||
"@budibase/client": "2.5.6-alpha.3",
|
"@budibase/client": "2.5.6-alpha.5",
|
||||||
"@budibase/frontend-core": "2.5.6-alpha.3",
|
"@budibase/frontend-core": "2.5.6-alpha.5",
|
||||||
"@budibase/shared-core": "2.5.6-alpha.3",
|
"@budibase/shared-core": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
"@fortawesome/fontawesome-svg-core": "^6.2.1",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
"@fortawesome/free-brands-svg-icons": "^6.2.1",
|
||||||
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
"@fortawesome/free-solid-svg-icons": "^6.2.1",
|
||||||
|
@ -93,13 +93,14 @@
|
||||||
"@roxi/routify": "2.18.5",
|
"@roxi/routify": "2.18.5",
|
||||||
"@sveltejs/vite-plugin-svelte": "1.0.1",
|
"@sveltejs/vite-plugin-svelte": "1.0.1",
|
||||||
"@testing-library/jest-dom": "^5.11.10",
|
"@testing-library/jest-dom": "^5.11.10",
|
||||||
"@testing-library/svelte": "^3.0.0",
|
"@testing-library/svelte": "^3.2.2",
|
||||||
"babel-jest": "^26.6.3",
|
"babel-jest": "^26.6.3",
|
||||||
"cypress": "^9.3.1",
|
"cypress": "^9.3.1",
|
||||||
"cypress-multi-reporters": "^1.6.0",
|
"cypress-multi-reporters": "^1.6.0",
|
||||||
"cypress-terminal-report": "^1.4.1",
|
"cypress-terminal-report": "^1.4.1",
|
||||||
"identity-obj-proxy": "^3.0.0",
|
"identity-obj-proxy": "^3.0.0",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
|
"jsdom": "^21.1.1",
|
||||||
"mochawesome": "^7.1.3",
|
"mochawesome": "^7.1.3",
|
||||||
"mochawesome-merge": "^4.2.1",
|
"mochawesome-merge": "^4.2.1",
|
||||||
"mochawesome-report-generator": "^6.2.0",
|
"mochawesome-report-generator": "^6.2.0",
|
||||||
|
@ -113,7 +114,8 @@
|
||||||
"ts-node": "10.8.1",
|
"ts-node": "10.8.1",
|
||||||
"tsconfig-paths": "4.0.0",
|
"tsconfig-paths": "4.0.0",
|
||||||
"typescript": "4.7.3",
|
"typescript": "4.7.3",
|
||||||
"vite": "^3.0.8"
|
"vite": "^3.0.8",
|
||||||
|
"vitest": "^0.29.2"
|
||||||
},
|
},
|
||||||
"gitHead": "115189f72a850bfb52b65ec61d932531bf327072"
|
"gitHead": "115189f72a850bfb52b65ec61d932531bf327072"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import * as jsonpatch from "fast-json-patch/index.mjs"
|
import * as jsonpatch from "fast-json-patch/index.mjs"
|
||||||
import { writable, derived, get } from "svelte/store"
|
import { writable, derived, get } from "svelte/store"
|
||||||
|
|
||||||
const Operations = {
|
export const Operations = {
|
||||||
Add: "Add",
|
Add: "Add",
|
||||||
Delete: "Delete",
|
Delete: "Delete",
|
||||||
Change: "Change",
|
Change: "Change",
|
||||||
}
|
}
|
||||||
|
|
||||||
const initialState = {
|
export const initialState = {
|
||||||
history: [],
|
history: [],
|
||||||
position: 0,
|
position: 0,
|
||||||
loading: false,
|
loading: false,
|
||||||
|
|
|
@ -0,0 +1,345 @@
|
||||||
|
import { it, expect, describe, beforeEach, vi } from "vitest"
|
||||||
|
import { Operations, initialState, createHistoryStore } from "./history"
|
||||||
|
|
||||||
|
import { writable, derived, get } from "svelte/store"
|
||||||
|
import * as jsonpatch from "fast-json-patch/index.mjs"
|
||||||
|
|
||||||
|
vi.mock("svelte/store", () => {
|
||||||
|
return {
|
||||||
|
writable: vi.fn(),
|
||||||
|
derived: vi.fn(),
|
||||||
|
get: vi.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vi.mock("fast-json-patch/index.mjs", () => {
|
||||||
|
return {
|
||||||
|
compare: vi.fn(),
|
||||||
|
deepClone: vi.fn(),
|
||||||
|
applyPatch: vi.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("admin store", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
|
||||||
|
ctx.writableReturn = { update: vi.fn(), subscribe: vi.fn(), set: vi.fn() }
|
||||||
|
writable.mockReturnValue(ctx.writableReturn)
|
||||||
|
|
||||||
|
ctx.derivedReturn = { subscribe: vi.fn() }
|
||||||
|
derived.mockReturnValue(ctx.derivedReturn)
|
||||||
|
|
||||||
|
ctx.getDoc = vi.fn().mockReturnValue({})
|
||||||
|
ctx.selectDoc = vi.fn().mockReturnValue({})
|
||||||
|
ctx.beforeAction = vi.fn()
|
||||||
|
ctx.afterAction = vi.fn()
|
||||||
|
|
||||||
|
ctx.returnedStore = createHistoryStore({
|
||||||
|
getDoc: ctx.getDoc,
|
||||||
|
selectDoc: ctx.selectDoc,
|
||||||
|
beforeAction: ctx.beforeAction,
|
||||||
|
afterAction: ctx.afterAction,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("init", () => {
|
||||||
|
it("inits the writable store with the default config", () => {
|
||||||
|
expect(writable).toHaveBeenCalledTimes(1)
|
||||||
|
expect(writable).toHaveBeenCalledWith(initialState)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("inits the derived store with the initial writable store and an update function", () => {
|
||||||
|
expect(derived).toHaveBeenCalledTimes(1)
|
||||||
|
expect(derived.calls[0][1]({ position: 0, history: [] })).toEqual({
|
||||||
|
position: 0,
|
||||||
|
history: [],
|
||||||
|
canUndo: false,
|
||||||
|
canRedo: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns the created store and methods to manipulate it", ctx => {
|
||||||
|
expect(ctx.returnedStore).toEqual({
|
||||||
|
subscribe: expect.toBe(ctx.derivedReturn.subscribe),
|
||||||
|
wrapSaveDoc: expect.toBeFunc(),
|
||||||
|
wrapDeleteDoc: expect.toBeFunc(),
|
||||||
|
reset: expect.toBeFunc(),
|
||||||
|
undo: expect.toBeFunc(),
|
||||||
|
redo: expect.toBeFunc(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("wrapSaveDoc", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.saveFn = vi.fn().mockResolvedValue("fn")
|
||||||
|
|
||||||
|
ctx.doc = { _id: "id" }
|
||||||
|
ctx.oldDoc = { _id: "oldDoc" }
|
||||||
|
ctx.newDoc = { _id: "newDoc" }
|
||||||
|
ctx.getDoc.mockReturnValue(ctx.oldDoc)
|
||||||
|
jsonpatch.deepClone.mockReturnValue(ctx.newDoc)
|
||||||
|
|
||||||
|
vi.stubGlobal("Math", { random: vi.fn() })
|
||||||
|
|
||||||
|
ctx.forwardPatch = { foo: 1 }
|
||||||
|
ctx.backwardsPatch = { bar: 2 }
|
||||||
|
|
||||||
|
jsonpatch.compare.mockReturnValueOnce(ctx.forwardPatch)
|
||||||
|
jsonpatch.compare.mockReturnValueOnce(ctx.backwardsPatch)
|
||||||
|
Math.random.mockReturnValue(1234)
|
||||||
|
|
||||||
|
const wrappedSaveFn = ctx.returnedStore.wrapSaveDoc(ctx.saveFn)
|
||||||
|
await wrappedSaveFn(ctx.doc, null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({})).toEqual({
|
||||||
|
loading: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("retrieves the old doc", ctx => {
|
||||||
|
expect(ctx.getDoc).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.getDoc).toHaveBeenCalledWith("id")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clones the new doc", ctx => {
|
||||||
|
expect(ctx.saveFn).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.saveFn).toHaveBeenCalledWith(ctx.doc)
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledTimes(1)
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledWith("fn")
|
||||||
|
})
|
||||||
|
|
||||||
|
it("creates the undo/redo patches", ctx => {
|
||||||
|
expect(jsonpatch.compare).toHaveBeenCalledTimes(2)
|
||||||
|
expect(jsonpatch.compare.calls[0]).toEqual([ctx.oldDoc, ctx.doc])
|
||||||
|
expect(jsonpatch.compare.calls[1]).toEqual([ctx.doc, ctx.oldDoc])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saves the operation", ctx => {
|
||||||
|
expect(
|
||||||
|
ctx.writableReturn.update.calls[1][0]({
|
||||||
|
history: [],
|
||||||
|
position: 0,
|
||||||
|
})
|
||||||
|
).toEqual({
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
type: Operations.Change,
|
||||||
|
backwardsPatch: ctx.backwardsPatch,
|
||||||
|
forwardPatch: ctx.forwardPatch,
|
||||||
|
doc: ctx.newDoc,
|
||||||
|
id: 1234,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
position: 1,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to not loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update).toHaveBeenCalledTimes(3)
|
||||||
|
expect(ctx.writableReturn.update.calls[2][0]({})).toEqual({
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("wrapDeleteDoc", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.deleteFn = vi.fn().mockResolvedValue("fn")
|
||||||
|
|
||||||
|
ctx.doc = { _id: "id" }
|
||||||
|
ctx.oldDoc = { _id: "oldDoc" }
|
||||||
|
jsonpatch.deepClone.mockReturnValue(ctx.oldDoc)
|
||||||
|
|
||||||
|
vi.stubGlobal("Math", { random: vi.fn() })
|
||||||
|
Math.random.mockReturnValue(1235)
|
||||||
|
|
||||||
|
const wrappedDeleteDoc = ctx.returnedStore.wrapDeleteDoc(ctx.deleteFn)
|
||||||
|
await wrappedDeleteDoc(ctx.doc, null)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({})).toEqual({
|
||||||
|
loading: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clones the doc", ctx => {
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledTimes(1)
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledWith(ctx.doc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the delete fn with the doc", ctx => {
|
||||||
|
expect(ctx.deleteFn).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.deleteFn).toHaveBeenCalledWith(ctx.doc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("saves the operation", ctx => {
|
||||||
|
expect(
|
||||||
|
ctx.writableReturn.update.calls[1][0]({
|
||||||
|
history: [],
|
||||||
|
position: 0,
|
||||||
|
})
|
||||||
|
).toEqual({
|
||||||
|
history: [
|
||||||
|
{
|
||||||
|
type: Operations.Delete,
|
||||||
|
doc: ctx.oldDoc,
|
||||||
|
id: 1235,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
position: 1,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to not loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update).toHaveBeenCalledTimes(3)
|
||||||
|
expect(ctx.writableReturn.update.calls[2][0]({})).toEqual({
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("reset", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.returnedStore.reset()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the store to the initial state", ctx => {
|
||||||
|
expect(ctx.writableReturn.set).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.writableReturn.set).toHaveBeenCalledWith(initialState)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("undo", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.history = [
|
||||||
|
{ type: Operations.Delete, doc: { _id: 1236, _rev: "rev" } },
|
||||||
|
]
|
||||||
|
ctx.derivedReturn = {
|
||||||
|
subscribe: vi.fn(),
|
||||||
|
canUndo: true,
|
||||||
|
history: ctx.history,
|
||||||
|
position: 1,
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
get.mockReturnValue(ctx.derivedReturn)
|
||||||
|
|
||||||
|
jsonpatch.deepClone.mockReturnValueOnce(ctx.history[0].doc)
|
||||||
|
|
||||||
|
ctx.newDoc = { _id: 1337 }
|
||||||
|
ctx.saveFn = vi.fn().mockResolvedValue(ctx.newDoc)
|
||||||
|
jsonpatch.deepClone.mockReturnValueOnce(ctx.newDoc)
|
||||||
|
|
||||||
|
// We need to create a wrapped saveFn before undo can be invoked
|
||||||
|
ctx.returnedStore.wrapSaveDoc(ctx.saveFn)
|
||||||
|
await ctx.returnedStore.undo()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({})).toEqual({
|
||||||
|
loading: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the beforeAction", ctx => {
|
||||||
|
expect(ctx.beforeAction).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.beforeAction).toHaveBeenCalledWith(ctx.history[0])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to the previous position", ctx => {
|
||||||
|
expect(
|
||||||
|
ctx.writableReturn.update.calls[1][0]({ history: [], position: 1 })
|
||||||
|
).toEqual({ history: [], position: 0 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("clones the doc", ctx => {
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledWith(ctx.history[0].doc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("deletes the doc's rev", ctx => {
|
||||||
|
expect(ctx.history[0].doc._rev).toBe(undefined)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the wrappedSaveFn", ctx => {
|
||||||
|
expect(jsonpatch.deepClone).toHaveBeenCalledWith(ctx.newDoc)
|
||||||
|
expect(ctx.saveFn).toHaveBeenCalledWith(ctx.history[0].doc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls selectDoc", ctx => {
|
||||||
|
expect(ctx.selectDoc).toHaveBeenCalledWith(ctx.newDoc._id)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to not loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[5][0]({})).toEqual({
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the afterAction", ctx => {
|
||||||
|
expect(ctx.afterAction).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.afterAction).toHaveBeenCalledWith(ctx.history[0])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("redo", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.history = [
|
||||||
|
{ type: Operations.Delete, doc: { _id: 1236, _rev: "rev" } },
|
||||||
|
]
|
||||||
|
ctx.derivedReturn = {
|
||||||
|
subscribe: vi.fn(),
|
||||||
|
canRedo: true,
|
||||||
|
history: ctx.history,
|
||||||
|
position: 0,
|
||||||
|
loading: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
get.mockReturnValue(ctx.derivedReturn)
|
||||||
|
|
||||||
|
ctx.latestDoc = { _id: 1337 }
|
||||||
|
ctx.getDoc.mockReturnValue(ctx.latestDoc)
|
||||||
|
|
||||||
|
// We need to create a wrapped deleteFn before redo can be invoked
|
||||||
|
ctx.deleteFn = vi.fn().mockResolvedValue(ctx.newDoc)
|
||||||
|
ctx.returnedStore.wrapDeleteDoc(ctx.deleteFn)
|
||||||
|
|
||||||
|
await ctx.returnedStore.redo()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({})).toEqual({
|
||||||
|
loading: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the beforeAction", ctx => {
|
||||||
|
expect(ctx.beforeAction).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.beforeAction).toHaveBeenCalledWith(ctx.history[0])
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to the next position", ctx => {
|
||||||
|
expect(
|
||||||
|
ctx.writableReturn.update.calls[1][0]({ history: [], position: 0 })
|
||||||
|
).toEqual({ history: [], position: 1 })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the wrappedDeleteFn", ctx => {
|
||||||
|
expect(ctx.deleteFn).toHaveBeenCalledWith(ctx.latestDoc)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state to not loading", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[5][0]({})).toEqual({
|
||||||
|
loading: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls the afterAction", ctx => {
|
||||||
|
expect(ctx.afterAction).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.afterAction).toHaveBeenCalledWith(ctx.history[0])
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -26,7 +26,7 @@
|
||||||
|
|
||||||
const external = actions.reduce((acc, elm) => {
|
const external = actions.reduce((acc, elm) => {
|
||||||
const [k, v] = elm
|
const [k, v] = elm
|
||||||
if (!v.internal) {
|
if (!v.internal && !v.custom) {
|
||||||
acc[k] = v
|
acc[k] = v
|
||||||
}
|
}
|
||||||
return acc
|
return acc
|
||||||
|
@ -41,6 +41,15 @@
|
||||||
return acc
|
return acc
|
||||||
}, {})
|
}, {})
|
||||||
|
|
||||||
|
const plugins = actions.reduce((acc, elm) => {
|
||||||
|
const [k, v] = elm
|
||||||
|
if (v.custom) {
|
||||||
|
acc[k] = v
|
||||||
|
}
|
||||||
|
return acc
|
||||||
|
}, {})
|
||||||
|
console.log(plugins)
|
||||||
|
|
||||||
const selectAction = action => {
|
const selectAction = action => {
|
||||||
actionVal = action
|
actionVal = action
|
||||||
selectedAction = action.name
|
selectedAction = action.name
|
||||||
|
@ -116,6 +125,26 @@
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</Layout>
|
</Layout>
|
||||||
|
|
||||||
|
{#if Object.keys(plugins).length}
|
||||||
|
<Layout noPadding gap="XS">
|
||||||
|
<Detail size="S">Plugins</Detail>
|
||||||
|
<div class="item-list">
|
||||||
|
{#each Object.entries(plugins) as [idx, action]}
|
||||||
|
<div
|
||||||
|
class="item"
|
||||||
|
class:selected={selectedAction === action.name}
|
||||||
|
on:click={() => selectAction(action)}
|
||||||
|
>
|
||||||
|
<div class="item-body">
|
||||||
|
<Icon name={action.icon} />
|
||||||
|
<Body size="XS">{action.name}</Body>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/each}
|
||||||
|
</div>
|
||||||
|
</Layout>
|
||||||
|
{/if}
|
||||||
</ModalContent>
|
</ModalContent>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
@ -126,7 +155,7 @@
|
||||||
}
|
}
|
||||||
.item-list {
|
.item-list {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
|
grid-template-columns: repeat(2, minmax(150px, 1fr));
|
||||||
grid-gap: var(--spectrum-alias-grid-baseline);
|
grid-gap: var(--spectrum-alias-grid-baseline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { it, expect, describe, beforeEach } from "vitest"
|
||||||
|
import { render, screen } from "@testing-library/svelte"
|
||||||
|
import "@testing-library/jest-dom"
|
||||||
|
|
||||||
|
import EditableLabel from "./EditableLabel.svelte"
|
||||||
|
|
||||||
|
describe("EditableLabel", () => {
|
||||||
|
describe('type of "heading"', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render(EditableLabel, { type: "heading", value: "foo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a heading", () => {
|
||||||
|
expect(screen.getByTestId("typography-heading")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe('type of "body"', () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render(EditableLabel, { type: "body", value: "foo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a body", () => {
|
||||||
|
expect(screen.getByTestId("typography-body")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("any other type", () => {
|
||||||
|
beforeEach(() => {
|
||||||
|
render(EditableLabel, { type: "", value: "foo" })
|
||||||
|
})
|
||||||
|
|
||||||
|
it("renders a label", () => {
|
||||||
|
expect(screen.getByTestId("label")).toBeInTheDocument()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { expect, describe, it } from "vitest"
|
||||||
import { breakQueryString, buildQueryString } from "../data/utils"
|
import { breakQueryString, buildQueryString } from "../data/utils"
|
||||||
|
|
||||||
describe("check query string utils", () => {
|
describe("check query string utils", () => {
|
||||||
|
@ -26,12 +27,16 @@ describe("check query string utils", () => {
|
||||||
|
|
||||||
it("should be able to build with a binding", () => {
|
it("should be able to build with a binding", () => {
|
||||||
const queryString = buildQueryString(obj2)
|
const queryString = buildQueryString(obj2)
|
||||||
expect(queryString).toBe("key1={{ binding.awd }}&key2={{ binding.sed }}%20%20")
|
expect(queryString).toBe(
|
||||||
|
"key1={{ binding.awd }}&key2={{ binding.sed }}%20%20"
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
it("should be able to break with a binding", () => {
|
it("should be able to break with a binding", () => {
|
||||||
const broken = breakQueryString("key1={{ binding.awd }}&key2={{ binding.sed }}%20%20")
|
const broken = breakQueryString(
|
||||||
|
"key1={{ binding.awd }}&key2={{ binding.sed }}%20%20"
|
||||||
|
)
|
||||||
expect(broken.key1).toBe(obj2.key1)
|
expect(broken.key1).toBe(obj2.key1)
|
||||||
expect(broken.key2).toBe(obj2.key2)
|
expect(broken.key2).toBe(obj2.key2)
|
||||||
})
|
})
|
||||||
})
|
})
|
|
@ -1,7 +1,7 @@
|
||||||
const { duplicateName } = require("../duplicate")
|
import { expect, describe, it } from "vitest"
|
||||||
|
import { duplicateName } from "../duplicate"
|
||||||
|
|
||||||
describe("duplicate", () => {
|
describe("duplicate", () => {
|
||||||
|
|
||||||
describe("duplicates a name ", () => {
|
describe("duplicates a name ", () => {
|
||||||
it("with a single existing", async () => {
|
it("with a single existing", async () => {
|
||||||
const names = ["foo"]
|
const names = ["foo"]
|
|
@ -3,23 +3,23 @@ import { API } from "api"
|
||||||
import { auth } from "stores/portal"
|
import { auth } from "stores/portal"
|
||||||
import { banner } from "@budibase/bbui"
|
import { banner } from "@budibase/bbui"
|
||||||
|
|
||||||
export function createAdminStore() {
|
export const DEFAULT_CONFIG = {
|
||||||
const DEFAULT_CONFIG = {
|
loaded: false,
|
||||||
loaded: false,
|
multiTenancy: false,
|
||||||
multiTenancy: false,
|
cloud: false,
|
||||||
cloud: false,
|
isDev: false,
|
||||||
isDev: false,
|
disableAccountPortal: false,
|
||||||
disableAccountPortal: false,
|
accountPortalUrl: "",
|
||||||
accountPortalUrl: "",
|
importComplete: false,
|
||||||
importComplete: false,
|
checklist: {
|
||||||
checklist: {
|
apps: { checked: false },
|
||||||
apps: { checked: false },
|
smtp: { checked: false },
|
||||||
smtp: { checked: false },
|
adminUser: { checked: false },
|
||||||
adminUser: { checked: false },
|
sso: { checked: false },
|
||||||
sso: { checked: false },
|
},
|
||||||
},
|
}
|
||||||
}
|
|
||||||
|
|
||||||
|
export function createAdminStore() {
|
||||||
const admin = writable(DEFAULT_CONFIG)
|
const admin = writable(DEFAULT_CONFIG)
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
|
|
|
@ -0,0 +1,268 @@
|
||||||
|
import { it, expect, describe, beforeEach, vi } from "vitest"
|
||||||
|
import { DEFAULT_CONFIG, createAdminStore } from "./admin"
|
||||||
|
|
||||||
|
import { writable, get } from "svelte/store"
|
||||||
|
import { API } from "api"
|
||||||
|
import { auth } from "stores/portal"
|
||||||
|
import { banner } from "@budibase/bbui"
|
||||||
|
|
||||||
|
vi.mock("stores/portal", () => {
|
||||||
|
return { auth: vi.fn() }
|
||||||
|
})
|
||||||
|
|
||||||
|
// explict mock that is overwritten later so that the singleton admin store doesn't throw an error when partially mocked
|
||||||
|
vi.mock("svelte/store", () => {
|
||||||
|
return {
|
||||||
|
writable: vi.fn(() => ({
|
||||||
|
subscribe: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
})),
|
||||||
|
get: vi.fn(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vi.mock("api", () => {
|
||||||
|
return {
|
||||||
|
API: {
|
||||||
|
checkImportComplete: vi.fn(),
|
||||||
|
getEnvironment: vi.fn(),
|
||||||
|
getSystemStatus: vi.fn(),
|
||||||
|
getChecklist: vi.fn(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vi.mock("@budibase/bbui", () => {
|
||||||
|
return { banner: { showStatus: vi.fn() } }
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("admin store", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
|
||||||
|
ctx.writableReturn = { update: vi.fn(), subscribe: vi.fn() }
|
||||||
|
writable.mockReturnValue(ctx.writableReturn)
|
||||||
|
|
||||||
|
ctx.returnedStore = createAdminStore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("inits the writable store with the default config", () => {
|
||||||
|
expect(writable).toHaveBeenCalledTimes(1)
|
||||||
|
expect(writable).toHaveBeenCalledWith(DEFAULT_CONFIG)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("returns the created store", ctx => {
|
||||||
|
expect(ctx.returnedStore).toEqual({
|
||||||
|
subscribe: expect.toBe(ctx.writableReturn.subscribe),
|
||||||
|
init: expect.toBeFunc(),
|
||||||
|
checkImportComplete: expect.toBeFunc(),
|
||||||
|
unload: expect.toBeFunc(),
|
||||||
|
getChecklist: expect.toBeFunc(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("init method", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
let getMockIndex = 0
|
||||||
|
|
||||||
|
ctx.getMockValues = [
|
||||||
|
{ tenantId: "tenantId" },
|
||||||
|
{ cloud: true },
|
||||||
|
{ status: { health: { passing: false } } },
|
||||||
|
]
|
||||||
|
|
||||||
|
get.mockImplementation(() => {
|
||||||
|
const value = ctx.getMockValues[getMockIndex]
|
||||||
|
getMockIndex++
|
||||||
|
|
||||||
|
return value
|
||||||
|
})
|
||||||
|
|
||||||
|
API.getChecklist.mockReturnValue("checklist")
|
||||||
|
|
||||||
|
API.getEnvironment.mockReturnValue({
|
||||||
|
multiTenancy: true,
|
||||||
|
cloud: true,
|
||||||
|
disableAccountPortal: true,
|
||||||
|
accountPortalUrl: "url",
|
||||||
|
isDev: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
API.getSystemStatus.mockReturnValue("status")
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getCheckList", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds the checklist to the store", ctx => {
|
||||||
|
expect(get).toHaveBeenNthCalledWith(1, auth)
|
||||||
|
expect(API.getChecklist).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.getChecklist).toHaveBeenCalledWith("tenantId")
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
checklist: "checklist",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getEnvironment", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("adds the environment to the store", ctx => {
|
||||||
|
expect(API.getEnvironment).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.getEnvironment).toHaveBeenCalledWith()
|
||||||
|
expect(ctx.writableReturn.update.calls[1][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
multiTenancy: true,
|
||||||
|
cloud: true,
|
||||||
|
disableAccountPortal: true,
|
||||||
|
accountPortalUrl: "url",
|
||||||
|
isDev: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("system status", () => {
|
||||||
|
describe("non cloud", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.getMockValues[1].cloud = false
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("getSystemStatus", () => {
|
||||||
|
expect(API.getSystemStatus).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("checkStatus", () => {
|
||||||
|
expect(get).toHaveBeenCalledTimes(2)
|
||||||
|
expect(banner.showStatus).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cloud with healthy admin status", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.getMockValues[1].cloud = true
|
||||||
|
ctx.getMockValues[2].status.health.passing = true
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("getSystemStatus", ctx => {
|
||||||
|
expect(get).toHaveBeenNthCalledWith(2, ctx.writableReturn)
|
||||||
|
expect(API.getSystemStatus).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.getEnvironment).toHaveBeenCalledWith()
|
||||||
|
expect(ctx.writableReturn.update.calls[2][0]({ foo: "foo" })).toEqual(
|
||||||
|
{ foo: "foo", status: "status" }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("checkStatus", ctx => {
|
||||||
|
expect(get).toHaveBeenCalledTimes(3)
|
||||||
|
expect(get).toHaveBeenNthCalledWith(3, ctx.writableReturn)
|
||||||
|
expect(banner.showStatus).toHaveBeenCalledTimes(0)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("cloud with unhealthy admin status", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.getMockValues[1].cloud = true
|
||||||
|
ctx.getMockValues[2].status.health.passing = false
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("getSystemStatus", ctx => {
|
||||||
|
expect(get).toHaveBeenNthCalledWith(2, ctx.writableReturn)
|
||||||
|
expect(API.getSystemStatus).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.getEnvironment).toHaveBeenCalledWith()
|
||||||
|
expect(ctx.writableReturn.update.calls[2][0]({ foo: "foo" })).toEqual(
|
||||||
|
{ foo: "foo", status: "status" }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("checkStatus", ctx => {
|
||||||
|
expect(get).toHaveBeenCalledTimes(3)
|
||||||
|
expect(get).toHaveBeenNthCalledWith(3, ctx.writableReturn)
|
||||||
|
expect(banner.showStatus).toHaveBeenCalledTimes(1)
|
||||||
|
expect(banner.showStatus).toHaveBeenCalledWith()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getEnvironment", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
await ctx.returnedStore.init()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("marks the store as loaded", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[3][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
loaded: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("checkImportComplete", () => {
|
||||||
|
describe("import complete", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
API.checkImportComplete.mockReturnValue({ imported: true })
|
||||||
|
await ctx.returnedStore.checkImportComplete()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("updates the store's importComplete parameter", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
importComplete: true,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("import not complete", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
// Can be null
|
||||||
|
API.checkImportComplete.mockReturnValue(null)
|
||||||
|
await ctx.returnedStore.checkImportComplete()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("updates the store's importComplete parameter", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
importComplete: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("unload", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.returnedStore.unload()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the store's loaded parameter to false", ctx => {
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({ loaded: true })).toEqual({
|
||||||
|
loaded: false,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("getChecklist", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
get.mockReturnValue({ tenantId: "tenantId" })
|
||||||
|
API.getChecklist.mockReturnValue("checklist")
|
||||||
|
await ctx.returnedStore.getChecklist()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("updates the store with the new checklist", ctx => {
|
||||||
|
expect(get).toHaveBeenNthCalledWith(1, auth)
|
||||||
|
expect(API.getChecklist).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.getChecklist).toHaveBeenCalledWith("tenantId")
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({ foo: "foo" })).toEqual({
|
||||||
|
foo: "foo",
|
||||||
|
checklist: "checklist",
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -0,0 +1,173 @@
|
||||||
|
import { it, expect, describe, beforeEach, vi } from "vitest"
|
||||||
|
import { createBackupsStore } from "./backups"
|
||||||
|
|
||||||
|
import { writable } from "svelte/store"
|
||||||
|
import { API } from "api"
|
||||||
|
|
||||||
|
vi.mock("svelte/store", () => {
|
||||||
|
return {
|
||||||
|
writable: vi.fn(() => ({
|
||||||
|
subscribe: vi.fn(),
|
||||||
|
update: vi.fn(),
|
||||||
|
})),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
vi.mock("api", () => {
|
||||||
|
return {
|
||||||
|
API: {
|
||||||
|
searchBackups: vi.fn(() => "searchBackupsReturn"),
|
||||||
|
restoreBackup: vi.fn(() => "restoreBackupReturn"),
|
||||||
|
deleteBackup: vi.fn(() => "deleteBackupReturn"),
|
||||||
|
createManualBackup: vi.fn(() => "createManualBackupReturn"),
|
||||||
|
updateBackup: vi.fn(() => "updateBackupReturn"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("backups store", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
vi.clearAllMocks()
|
||||||
|
|
||||||
|
ctx.writableReturn = { update: vi.fn(), subscribe: vi.fn() }
|
||||||
|
writable.mockReturnValue(ctx.writableReturn)
|
||||||
|
|
||||||
|
ctx.returnedStore = createBackupsStore()
|
||||||
|
})
|
||||||
|
|
||||||
|
it("inits the writable store with the default config", () => {
|
||||||
|
expect(writable).toHaveBeenCalledTimes(1)
|
||||||
|
expect(writable).toHaveBeenCalledWith({})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("createManualBackup", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.appId = "appId"
|
||||||
|
ctx.value = await ctx.returnedStore.createManualBackup(ctx.appId)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls and returns the API createManualBackup method", ctx => {
|
||||||
|
expect(API.createManualBackup).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.createManualBackup).toHaveBeenCalledWith(ctx.appId)
|
||||||
|
expect(ctx.value).toBe("createManualBackupReturn")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("searchBackups", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.appId = "appId"
|
||||||
|
ctx.trigger = "trigger"
|
||||||
|
ctx.type = "type"
|
||||||
|
ctx.page = "page"
|
||||||
|
ctx.startDate = "startDate"
|
||||||
|
ctx.endDate = "endDate"
|
||||||
|
ctx.value = await ctx.returnedStore.searchBackups({
|
||||||
|
appId: ctx.appId,
|
||||||
|
trigger: ctx.trigger,
|
||||||
|
type: ctx.type,
|
||||||
|
page: ctx.page,
|
||||||
|
startDate: ctx.startDate,
|
||||||
|
endDate: ctx.endDate,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls and returns the API searchBackups method", ctx => {
|
||||||
|
expect(API.searchBackups).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.searchBackups).toHaveBeenCalledWith({
|
||||||
|
appId: ctx.appId,
|
||||||
|
trigger: ctx.trigger,
|
||||||
|
type: ctx.type,
|
||||||
|
page: ctx.page,
|
||||||
|
startDate: ctx.startDate,
|
||||||
|
endDate: ctx.endDate,
|
||||||
|
})
|
||||||
|
expect(ctx.value).toBe("searchBackupsReturn")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("selectBackup", () => {
|
||||||
|
beforeEach(ctx => {
|
||||||
|
ctx.backupId = "backupId"
|
||||||
|
ctx.returnedStore.selectBackup(ctx.backupId)
|
||||||
|
})
|
||||||
|
|
||||||
|
it("sets the state with the selected backup", ctx => {
|
||||||
|
expect(ctx.writableReturn.update).toHaveBeenCalledTimes(1)
|
||||||
|
expect(ctx.writableReturn.update.calls[0][0]({})).toEqual({
|
||||||
|
selectedBackup: ctx.backupId,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("deleteBackup", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.appId = "appId"
|
||||||
|
ctx.backupId = "backupId"
|
||||||
|
ctx.value = await ctx.returnedStore.deleteBackup({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls and returns the API deleteBackup method", ctx => {
|
||||||
|
expect(API.deleteBackup).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.deleteBackup).toHaveBeenCalledWith({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
})
|
||||||
|
expect(ctx.value).toBe("deleteBackupReturn")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("restoreBackup", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.appId = "appId"
|
||||||
|
ctx.backupId = "backupId"
|
||||||
|
ctx.$name = "name" // `name` is used by some sort of internal ctx thing and is readonly
|
||||||
|
ctx.value = await ctx.returnedStore.restoreBackup({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
name: ctx.$name,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls and returns the API restoreBackup method", ctx => {
|
||||||
|
expect(API.restoreBackup).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.restoreBackup).toHaveBeenCalledWith({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
name: ctx.$name,
|
||||||
|
})
|
||||||
|
expect(ctx.value).toBe("restoreBackupReturn")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("updateBackup", () => {
|
||||||
|
beforeEach(async ctx => {
|
||||||
|
ctx.appId = "appId"
|
||||||
|
ctx.backupId = "backupId"
|
||||||
|
ctx.$name = "name" // `name` is used by some sort of internal ctx thing and is readonly
|
||||||
|
ctx.value = await ctx.returnedStore.updateBackup({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
name: ctx.$name,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
it("calls and returns the API updateBackup method", ctx => {
|
||||||
|
expect(API.updateBackup).toHaveBeenCalledTimes(1)
|
||||||
|
expect(API.updateBackup).toHaveBeenCalledWith({
|
||||||
|
appId: ctx.appId,
|
||||||
|
backupId: ctx.backupId,
|
||||||
|
name: ctx.$name,
|
||||||
|
})
|
||||||
|
expect(ctx.value).toBe("updateBackupReturn")
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
describe("subscribe", () => {
|
||||||
|
it("calls and returns the API updateBackup method", ctx => {
|
||||||
|
expect(ctx.returnedStore.subscribe).toBe(ctx.writableReturn.subscribe)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
})
|
|
@ -15,6 +15,11 @@ export default defineConfig(({ mode }) => {
|
||||||
const isProduction = mode === "production"
|
const isProduction = mode === "production"
|
||||||
const env = loadEnv(mode, process.cwd())
|
const env = loadEnv(mode, process.cwd())
|
||||||
return {
|
return {
|
||||||
|
test: {
|
||||||
|
setupFiles: ["./vitest.setup.js"],
|
||||||
|
globals: true,
|
||||||
|
environment: "jsdom",
|
||||||
|
},
|
||||||
server: {
|
server: {
|
||||||
fs: {
|
fs: {
|
||||||
strict: false,
|
strict: false,
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
import { expect } from "vitest"
|
||||||
|
|
||||||
|
expect.extend({
|
||||||
|
toBeFunc: received => {
|
||||||
|
if (typeof received === "function") {
|
||||||
|
return {
|
||||||
|
pass: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: () => `expected ${received} to be a function`,
|
||||||
|
pass: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
toBe: (received, expected) => {
|
||||||
|
if (received === expected) {
|
||||||
|
return {
|
||||||
|
pass: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
message: () => `expected ${received} to be ${expected}`,
|
||||||
|
pass: false,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
|
@ -7,3 +7,6 @@ envoy.yaml
|
||||||
*.tar.gz
|
*.tar.gz
|
||||||
prebuilds/
|
prebuilds/
|
||||||
dist/
|
dist/
|
||||||
|
budibase-automation/
|
||||||
|
budibase-component/
|
||||||
|
budibase-datasource/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
@ -29,9 +29,9 @@
|
||||||
"outputPath": "build"
|
"outputPath": "build"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "2.5.6-alpha.3",
|
"@budibase/backend-core": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@budibase/types": "2.5.6-alpha.3",
|
"@budibase/types": "2.5.6-alpha.5",
|
||||||
"axios": "0.21.2",
|
"axios": "0.21.2",
|
||||||
"chalk": "4.1.0",
|
"chalk": "4.1.0",
|
||||||
"cli-progress": "3.11.2",
|
"cli-progress": "3.11.2",
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
import { logging } from "@budibase/backend-core"
|
||||||
|
logging.disableLogger()
|
||||||
import "./prebuilds"
|
import "./prebuilds"
|
||||||
import "./environment"
|
import "./environment"
|
||||||
import { getCommands } from "./options"
|
import { getCommands } from "./options"
|
||||||
|
|
|
@ -54,7 +54,7 @@ async function init(opts: PluginOpts) {
|
||||||
if (!type || !PLUGIN_TYPE_ARR.includes(type)) {
|
if (!type || !PLUGIN_TYPE_ARR.includes(type)) {
|
||||||
console.log(
|
console.log(
|
||||||
error(
|
error(
|
||||||
"Please provide a type to init, either 'component' or 'datasource'."
|
"Please provide a type to init, either 'component', 'datasource' or 'automation'."
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -19,11 +19,11 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.5.6-alpha.3",
|
"@budibase/bbui": "2.5.6-alpha.5",
|
||||||
"@budibase/frontend-core": "2.5.6-alpha.3",
|
"@budibase/frontend-core": "2.5.6-alpha.5",
|
||||||
"@budibase/shared-core": "2.5.6-alpha.3",
|
"@budibase/shared-core": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@budibase/types": "2.5.6-alpha.3",
|
"@budibase/types": "2.5.6-alpha.5",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.3",
|
||||||
"@spectrum-css/card": "^3.0.3",
|
"@spectrum-css/card": "^3.0.3",
|
||||||
"@spectrum-css/divider": "^1.0.3",
|
"@spectrum-css/divider": "^1.0.3",
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "2.5.6-alpha.3",
|
"@budibase/bbui": "2.5.6-alpha.5",
|
||||||
"@budibase/shared-core": "2.5.6-alpha.3",
|
"@budibase/shared-core": "2.5.6-alpha.5",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/sdk",
|
"name": "@budibase/sdk",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase Public API SDK",
|
"description": "Budibase Public API SDK",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -45,12 +45,12 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "10.0.3",
|
"@apidevtools/swagger-parser": "10.0.3",
|
||||||
"@budibase/backend-core": "2.5.6-alpha.3",
|
"@budibase/backend-core": "2.5.6-alpha.5",
|
||||||
"@budibase/client": "2.5.6-alpha.3",
|
"@budibase/client": "2.5.6-alpha.5",
|
||||||
"@budibase/pro": "2.5.6-alpha.3",
|
"@budibase/pro": "2.5.6-alpha.5",
|
||||||
"@budibase/shared-core": "2.5.6-alpha.3",
|
"@budibase/shared-core": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@budibase/types": "2.5.6-alpha.3",
|
"@budibase/types": "2.5.6-alpha.5",
|
||||||
"@bull-board/api": "3.7.0",
|
"@bull-board/api": "3.7.0",
|
||||||
"@bull-board/koa": "3.9.4",
|
"@bull-board/koa": "3.9.4",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -16,9 +16,15 @@ import { setTestFlag, clearTestFlag } from "../../utilities/redis"
|
||||||
import { context, cache, events } from "@budibase/backend-core"
|
import { context, cache, events } from "@budibase/backend-core"
|
||||||
import { automations } from "@budibase/pro"
|
import { automations } from "@budibase/pro"
|
||||||
import { Automation, BBContext } from "@budibase/types"
|
import { Automation, BBContext } from "@budibase/types"
|
||||||
|
import { getActionDefinitions as actionDefs } from "../../automations/actions"
|
||||||
|
|
||||||
const ACTION_DEFS = removeDeprecated(actions.ACTION_DEFINITIONS)
|
async function getActionDefinitions() {
|
||||||
const TRIGGER_DEFS = removeDeprecated(triggers.TRIGGER_DEFINITIONS)
|
return removeDeprecated(await actionDefs())
|
||||||
|
}
|
||||||
|
|
||||||
|
function getTriggerDefinitions() {
|
||||||
|
return removeDeprecated(triggers.TRIGGER_DEFINITIONS)
|
||||||
|
}
|
||||||
|
|
||||||
/*************************
|
/*************************
|
||||||
* *
|
* *
|
||||||
|
@ -228,17 +234,17 @@ export async function clearLogError(ctx: BBContext) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getActionList(ctx: BBContext) {
|
export async function getActionList(ctx: BBContext) {
|
||||||
ctx.body = ACTION_DEFS
|
ctx.body = await getActionDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTriggerList(ctx: BBContext) {
|
export async function getTriggerList(ctx: BBContext) {
|
||||||
ctx.body = TRIGGER_DEFS
|
ctx.body = getTriggerDefinitions()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getDefinitionList(ctx: BBContext) {
|
export async function getDefinitionList(ctx: BBContext) {
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
trigger: TRIGGER_DEFS,
|
trigger: getTriggerDefinitions(),
|
||||||
action: ACTION_DEFS,
|
action: await getActionDefinitions(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,31 +1,11 @@
|
||||||
import { npmUpload, urlUpload, githubUpload, fileUpload } from "./uploaders"
|
import { npmUpload, urlUpload, githubUpload } from "./uploaders"
|
||||||
import {
|
import { plugins as pluginCore } from "@budibase/backend-core"
|
||||||
plugins as pluginCore,
|
import { PluginType, FileType, PluginSource } from "@budibase/types"
|
||||||
db as dbCore,
|
|
||||||
tenancy,
|
|
||||||
objectStore,
|
|
||||||
} from "@budibase/backend-core"
|
|
||||||
import { PluginType, FileType, PluginSource, Plugin } from "@budibase/types"
|
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import { ClientAppSocket } from "../../../websocket"
|
import { ClientAppSocket } from "../../../websocket"
|
||||||
|
import sdk from "../../../sdk"
|
||||||
import { sdk as pro } from "@budibase/pro"
|
import { sdk as pro } from "@budibase/pro"
|
||||||
|
|
||||||
export async function getPlugins(type?: PluginType) {
|
|
||||||
const db = tenancy.getGlobalDB()
|
|
||||||
const response = await db.allDocs(
|
|
||||||
dbCore.getPluginParams(null, {
|
|
||||||
include_docs: true,
|
|
||||||
})
|
|
||||||
)
|
|
||||||
let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
|
|
||||||
plugins = objectStore.enrichPluginURLs(plugins)
|
|
||||||
if (type) {
|
|
||||||
return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
|
|
||||||
} else {
|
|
||||||
return plugins
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export async function upload(ctx: any) {
|
export async function upload(ctx: any) {
|
||||||
const plugins: FileType[] =
|
const plugins: FileType[] =
|
||||||
ctx.request.files.file.length > 1
|
ctx.request.files.file.length > 1
|
||||||
|
@ -35,7 +15,7 @@ export async function upload(ctx: any) {
|
||||||
let docs = []
|
let docs = []
|
||||||
// can do single or multiple plugins
|
// can do single or multiple plugins
|
||||||
for (let plugin of plugins) {
|
for (let plugin of plugins) {
|
||||||
const doc = await processUploadedPlugin(plugin, PluginSource.FILE)
|
const doc = await sdk.plugins.processUploaded(plugin, PluginSource.FILE)
|
||||||
docs.push(doc)
|
docs.push(doc)
|
||||||
}
|
}
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
|
@ -105,7 +85,7 @@ export async function create(ctx: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function fetch(ctx: any) {
|
export async function fetch(ctx: any) {
|
||||||
ctx.body = await getPlugins()
|
ctx.body = await sdk.plugins.fetch()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: any) {
|
export async function destroy(ctx: any) {
|
||||||
|
@ -119,20 +99,3 @@ export async function destroy(ctx: any) {
|
||||||
ctx.throw(400, err.message)
|
ctx.throw(400, err.message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function processUploadedPlugin(
|
|
||||||
plugin: FileType,
|
|
||||||
source?: PluginSource
|
|
||||||
) {
|
|
||||||
const { metadata, directory } = await fileUpload(plugin)
|
|
||||||
pluginCore.validate(metadata?.schema)
|
|
||||||
|
|
||||||
// Only allow components in cloud
|
|
||||||
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
|
|
||||||
throw new Error("Only component plugins are supported outside of self-host")
|
|
||||||
}
|
|
||||||
|
|
||||||
const doc = await pro.plugins.storePlugin(metadata, directory, source)
|
|
||||||
ClientAppSocket.emit("plugin-update", { name: doc.name, hash: doc.hash })
|
|
||||||
return doc
|
|
||||||
}
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ const {
|
||||||
const setup = require("./utilities")
|
const setup = require("./utilities")
|
||||||
const { basicAutomation, newAutomation, automationTrigger, automationStep } = setup.structures
|
const { basicAutomation, newAutomation, automationTrigger, automationStep } = setup.structures
|
||||||
const MAX_RETRIES = 4
|
const MAX_RETRIES = 4
|
||||||
const { TRIGGER_DEFINITIONS, ACTION_DEFINITIONS } = require("../../../automations")
|
const { TRIGGER_DEFINITIONS, BUILTIN_ACTION_DEFINITIONS } = require("../../../automations")
|
||||||
const { events } = require("@budibase/backend-core")
|
const { events } = require("@budibase/backend-core")
|
||||||
|
|
||||||
|
|
||||||
|
@ -55,7 +55,7 @@ describe("/automations", () => {
|
||||||
.expect('Content-Type', /json/)
|
.expect('Content-Type', /json/)
|
||||||
.expect(200)
|
.expect(200)
|
||||||
|
|
||||||
let definitionsLength = Object.keys(ACTION_DEFINITIONS).length
|
let definitionsLength = Object.keys(BUILTIN_ACTION_DEFINITIONS).length
|
||||||
definitionsLength-- // OUTGOING_WEBHOOK is deprecated
|
definitionsLength-- // OUTGOING_WEBHOOK is deprecated
|
||||||
|
|
||||||
expect(Object.keys(res.body.action).length).toBeGreaterThanOrEqual(definitionsLength)
|
expect(Object.keys(res.body.action).length).toBeGreaterThanOrEqual(definitionsLength)
|
||||||
|
|
|
@ -15,7 +15,14 @@ import * as delay from "./steps/delay"
|
||||||
import * as queryRow from "./steps/queryRows"
|
import * as queryRow from "./steps/queryRows"
|
||||||
import * as loop from "./steps/loop"
|
import * as loop from "./steps/loop"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { AutomationStepSchema, AutomationStepInput } from "@budibase/types"
|
import {
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepInput,
|
||||||
|
PluginType,
|
||||||
|
AutomationStep,
|
||||||
|
} from "@budibase/types"
|
||||||
|
import sdk from "../sdk"
|
||||||
|
import { getAutomationPlugin } from "../utilities/fileSystem"
|
||||||
|
|
||||||
const ACTION_IMPLS: Record<
|
const ACTION_IMPLS: Record<
|
||||||
string,
|
string,
|
||||||
|
@ -38,25 +45,26 @@ const ACTION_IMPLS: Record<
|
||||||
zapier: zapier.run,
|
zapier: zapier.run,
|
||||||
integromat: integromat.run,
|
integromat: integromat.run,
|
||||||
}
|
}
|
||||||
export const ACTION_DEFINITIONS: Record<string, AutomationStepSchema> = {
|
export const BUILTIN_ACTION_DEFINITIONS: Record<string, AutomationStepSchema> =
|
||||||
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
{
|
||||||
CREATE_ROW: createRow.definition,
|
SEND_EMAIL_SMTP: sendSmtpEmail.definition,
|
||||||
UPDATE_ROW: updateRow.definition,
|
CREATE_ROW: createRow.definition,
|
||||||
DELETE_ROW: deleteRow.definition,
|
UPDATE_ROW: updateRow.definition,
|
||||||
OUTGOING_WEBHOOK: outgoingWebhook.definition,
|
DELETE_ROW: deleteRow.definition,
|
||||||
EXECUTE_SCRIPT: executeScript.definition,
|
OUTGOING_WEBHOOK: outgoingWebhook.definition,
|
||||||
EXECUTE_QUERY: executeQuery.definition,
|
EXECUTE_SCRIPT: executeScript.definition,
|
||||||
SERVER_LOG: serverLog.definition,
|
EXECUTE_QUERY: executeQuery.definition,
|
||||||
DELAY: delay.definition,
|
SERVER_LOG: serverLog.definition,
|
||||||
FILTER: filter.definition,
|
DELAY: delay.definition,
|
||||||
QUERY_ROWS: queryRow.definition,
|
FILTER: filter.definition,
|
||||||
LOOP: loop.definition,
|
QUERY_ROWS: queryRow.definition,
|
||||||
// these used to be lowercase step IDs, maintain for backwards compat
|
LOOP: loop.definition,
|
||||||
discord: discord.definition,
|
// these used to be lowercase step IDs, maintain for backwards compat
|
||||||
slack: slack.definition,
|
discord: discord.definition,
|
||||||
zapier: zapier.definition,
|
slack: slack.definition,
|
||||||
integromat: integromat.definition,
|
zapier: zapier.definition,
|
||||||
}
|
integromat: integromat.definition,
|
||||||
|
}
|
||||||
|
|
||||||
// don't add the bash script/definitions unless in self host
|
// don't add the bash script/definitions unless in self host
|
||||||
// the fact this isn't included in any definitions means it cannot be
|
// the fact this isn't included in any definitions means it cannot be
|
||||||
|
@ -66,12 +74,36 @@ if (env.SELF_HOSTED) {
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
ACTION_IMPLS["EXECUTE_BASH"] = bash.run
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
BUILTIN_ACTION_DEFINITIONS["EXECUTE_BASH"] = bash.definition
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getActionDefinitions() {
|
||||||
|
const actionDefinitions = BUILTIN_ACTION_DEFINITIONS
|
||||||
|
if (env.SELF_HOSTED) {
|
||||||
|
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
||||||
|
for (let plugin of plugins) {
|
||||||
|
const schema = plugin.schema.schema as AutomationStep
|
||||||
|
actionDefinitions[schema.stepId] = {
|
||||||
|
...schema,
|
||||||
|
custom: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return actionDefinitions
|
||||||
}
|
}
|
||||||
|
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
export async function getAction(actionName: string) {
|
export async function getAction(stepId: string) {
|
||||||
if (ACTION_IMPLS[actionName] != null) {
|
if (ACTION_IMPLS[stepId] != null) {
|
||||||
return ACTION_IMPLS[actionName]
|
return ACTION_IMPLS[stepId]
|
||||||
|
}
|
||||||
|
// must be a plugin
|
||||||
|
if (env.SELF_HOSTED) {
|
||||||
|
const plugins = await sdk.plugins.fetch(PluginType.AUTOMATION)
|
||||||
|
const found = plugins.find(plugin => plugin.schema.schema.stepId === stepId)
|
||||||
|
if (!found) {
|
||||||
|
throw new Error(`Unable to find action implementation for "${stepId}"`)
|
||||||
|
}
|
||||||
|
return (await getAutomationPlugin(found)).action
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ import BullQueue from "bull"
|
||||||
export { automationQueue } from "./bullboard"
|
export { automationQueue } from "./bullboard"
|
||||||
export { shutdown } from "./bullboard"
|
export { shutdown } from "./bullboard"
|
||||||
export { TRIGGER_DEFINITIONS } from "./triggers"
|
export { TRIGGER_DEFINITIONS } from "./triggers"
|
||||||
export { ACTION_DEFINITIONS } from "./actions"
|
export { BUILTIN_ACTION_DEFINITIONS, getActionDefinitions } from "./actions"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This module is built purely to kick off the worker farm and manage the inputs/outputs
|
* This module is built purely to kick off the worker farm and manage the inputs/outputs
|
||||||
|
|
|
@ -4,8 +4,11 @@ import * as automationUtils from "../automationUtils"
|
||||||
import environment from "../../environment"
|
import environment from "../../environment"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -13,7 +16,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Execute a bash command",
|
tagline: "Execute a bash command",
|
||||||
icon: "JourneyEvent",
|
icon: "JourneyEvent",
|
||||||
description: "Run a bash script",
|
description: "Run a bash script",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.EXECUTE_BASH,
|
stepId: AutomationActionStepId.EXECUTE_BASH,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -21,8 +24,8 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
code: {
|
code: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "code",
|
customType: AutomationCustomIOType.CODE,
|
||||||
title: "Code",
|
title: "Code",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -31,16 +34,16 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
stdout: {
|
stdout: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "Standard output of your bash command or script",
|
description: "Standard output of your bash command or script",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the command was successful",
|
description: "Whether the command was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
required: ["stdout"],
|
||||||
},
|
},
|
||||||
required: ["stdout"],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,11 @@ import { cleanUpRow, getError } from "../automationUtils"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,7 +15,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Create a {{inputs.enriched.table.name}} row",
|
tagline: "Create a {{inputs.enriched.table.name}} row",
|
||||||
icon: "TableRowAddBottom",
|
icon: "TableRowAddBottom",
|
||||||
description: "Add a row to your database",
|
description: "Add a row to your database",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.CREATE_ROW,
|
stepId: AutomationActionStepId.CREATE_ROW,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -20,14 +23,14 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
required: ["tableId"],
|
required: ["tableId"],
|
||||||
},
|
},
|
||||||
|
@ -37,24 +40,24 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The new row",
|
description: "The new row",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The response from the table",
|
description: "The response from the table",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the row creation was successful",
|
description: "Whether the row creation was successful",
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The identifier of the new row",
|
description: "The identifier of the new row",
|
||||||
},
|
},
|
||||||
revision: {
|
revision: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The revision of the new row",
|
description: "The revision of the new row",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
import { wait } from "../../utilities"
|
import { wait } from "../../utilities"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -17,7 +19,7 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
time: {
|
time: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
title: "Delay in milliseconds",
|
title: "Delay in milliseconds",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -26,14 +28,14 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the delay was successful",
|
description: "Whether the delay was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["success"],
|
required: ["success"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "LOGIC",
|
type: AutomationStepType.LOGIC,
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function run({ inputs }: AutomationStepInput) {
|
export async function run({ inputs }: AutomationStepInput) {
|
||||||
|
|
|
@ -3,8 +3,11 @@ import { buildCtx } from "./utils"
|
||||||
import { getError } from "../automationUtils"
|
import { getError } from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationCustomIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,7 +15,7 @@ export const definition: AutomationStepSchema = {
|
||||||
icon: "TableRowRemoveCenter",
|
icon: "TableRowRemoveCenter",
|
||||||
name: "Delete Row",
|
name: "Delete Row",
|
||||||
tagline: "Delete a {{inputs.enriched.table.name}} row",
|
tagline: "Delete a {{inputs.enriched.table.name}} row",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
stepId: AutomationActionStepId.DELETE_ROW,
|
stepId: AutomationActionStepId.DELETE_ROW,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -20,12 +23,12 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Row ID",
|
title: "Row ID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -34,16 +37,16 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The deleted row",
|
description: "The deleted row",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The response from the table",
|
description: "The response from the table",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the deletion was successful",
|
description: "Whether the deletion was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
const DEFAULT_USERNAME = "Budibase Automate"
|
const DEFAULT_USERNAME = "Budibase Automate"
|
||||||
|
@ -15,26 +17,26 @@ export const definition: AutomationStepSchema = {
|
||||||
description: "Send a message to a Discord server",
|
description: "Send a message to a Discord server",
|
||||||
icon: "ri-discord-line",
|
icon: "ri-discord-line",
|
||||||
stepId: AutomationActionStepId.discord,
|
stepId: AutomationActionStepId.discord,
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
url: {
|
url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Discord Webhook URL",
|
title: "Discord Webhook URL",
|
||||||
},
|
},
|
||||||
username: {
|
username: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Bot Name",
|
title: "Bot Name",
|
||||||
},
|
},
|
||||||
avatar_url: {
|
avatar_url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Bot Avatar URL",
|
title: "Bot Avatar URL",
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Message",
|
title: "Message",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -43,15 +45,15 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
httpStatus: {
|
httpStatus: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "The HTTP status code of the request",
|
description: "The HTTP status code of the request",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The response from the Discord Webhook",
|
description: "The response from the Discord Webhook",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the message sent successfully",
|
description: "Whether the message sent successfully",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,8 +3,11 @@ import { buildCtx } from "./utils"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,7 +15,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Execute Data Connector",
|
tagline: "Execute Data Connector",
|
||||||
icon: "Data",
|
icon: "Data",
|
||||||
description: "Execute a query in an external data connector",
|
description: "Execute a query in an external data connector",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
stepId: AutomationActionStepId.EXECUTE_QUERY,
|
stepId: AutomationActionStepId.EXECUTE_QUERY,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -20,14 +23,14 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
query: {
|
query: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
properties: {
|
properties: {
|
||||||
queryId: {
|
queryId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "query",
|
customType: AutomationCustomIOType.QUERY,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
customType: "queryParams",
|
customType: AutomationCustomIOType.QUERY_PARAMS,
|
||||||
title: "Parameters",
|
title: "Parameters",
|
||||||
required: ["queryId"],
|
required: ["queryId"],
|
||||||
},
|
},
|
||||||
|
@ -37,21 +40,21 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The response from the datasource execution",
|
description: "The response from the datasource execution",
|
||||||
},
|
},
|
||||||
info: {
|
info: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description:
|
description:
|
||||||
"Some query types may return extra data, like headers from a REST query",
|
"Some query types may return extra data, like headers from a REST query",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
required: ["response", "success"],
|
||||||
},
|
},
|
||||||
required: ["response", "success"],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,8 +3,11 @@ import { buildCtx } from "./utils"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,7 +15,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Execute JavaScript Code",
|
tagline: "Execute JavaScript Code",
|
||||||
icon: "Code",
|
icon: "Code",
|
||||||
description: "Run a piece of JavaScript code in your automation",
|
description: "Run a piece of JavaScript code in your automation",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.EXECUTE_SCRIPT,
|
stepId: AutomationActionStepId.EXECUTE_SCRIPT,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -20,8 +23,8 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
code: {
|
code: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "code",
|
customType: AutomationCustomIOType.CODE,
|
||||||
title: "Code",
|
title: "Code",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -30,16 +33,16 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
value: {
|
value: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The result of the return statement",
|
description: "The result of the return statement",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
required: ["success"],
|
||||||
},
|
},
|
||||||
required: ["success"],
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const FilterConditions = {
|
export const FilterConditions = {
|
||||||
|
@ -24,7 +26,7 @@ export const definition: AutomationStepSchema = {
|
||||||
icon: "Branch2",
|
icon: "Branch2",
|
||||||
description:
|
description:
|
||||||
"Conditionally halt automations which do not meet certain conditions",
|
"Conditionally halt automations which do not meet certain conditions",
|
||||||
type: "LOGIC",
|
type: AutomationStepType.LOGIC,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.FILTER,
|
stepId: AutomationActionStepId.FILTER,
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -34,17 +36,17 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
field: {
|
field: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Reference Value",
|
title: "Reference Value",
|
||||||
},
|
},
|
||||||
condition: {
|
condition: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Condition",
|
title: "Condition",
|
||||||
enum: Object.values(FilterConditions),
|
enum: Object.values(FilterConditions),
|
||||||
pretty: Object.values(PrettyFilterConditions),
|
pretty: Object.values(PrettyFilterConditions),
|
||||||
},
|
},
|
||||||
value: {
|
value: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Comparison Value",
|
title: "Comparison Value",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -53,11 +55,11 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
result: {
|
result: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the logic block passed",
|
description: "Whether the logic block passed",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -13,34 +15,34 @@ export const definition: AutomationStepSchema = {
|
||||||
"Performs a webhook call to Integromat and gets the response (if configured)",
|
"Performs a webhook call to Integromat and gets the response (if configured)",
|
||||||
icon: "ri-shut-down-line",
|
icon: "ri-shut-down-line",
|
||||||
stepId: AutomationActionStepId.integromat,
|
stepId: AutomationActionStepId.integromat,
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
url: {
|
url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Webhook URL",
|
title: "Webhook URL",
|
||||||
},
|
},
|
||||||
value1: {
|
value1: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Input Value 1",
|
title: "Input Value 1",
|
||||||
},
|
},
|
||||||
value2: {
|
value2: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Input Value 2",
|
title: "Input Value 2",
|
||||||
},
|
},
|
||||||
value3: {
|
value3: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Input Value 3",
|
title: "Input Value 3",
|
||||||
},
|
},
|
||||||
value4: {
|
value4: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Input Value 4",
|
title: "Input Value 4",
|
||||||
},
|
},
|
||||||
value5: {
|
value5: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Input Value 5",
|
title: "Input Value 5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -49,15 +51,15 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether call was successful",
|
description: "Whether call was successful",
|
||||||
},
|
},
|
||||||
httpStatus: {
|
httpStatus: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "The HTTP status code returned",
|
description: "The HTTP status code returned",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The webhook response - this can have properties",
|
description: "The webhook response - this can have properties",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,4 +1,10 @@
|
||||||
import { AutomationActionStepId, AutomationStepSchema } from "@budibase/types"
|
import {
|
||||||
|
AutomationActionStepId,
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
name: "Looping",
|
name: "Looping",
|
||||||
|
@ -12,19 +18,19 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
option: {
|
option: {
|
||||||
customType: "loopOption",
|
customType: AutomationCustomIOType.LOOP_OPTION,
|
||||||
title: "Input type",
|
title: "Input type",
|
||||||
},
|
},
|
||||||
binding: {
|
binding: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Binding / Value",
|
title: "Binding / Value",
|
||||||
},
|
},
|
||||||
iterations: {
|
iterations: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
title: "Max loop iterations",
|
title: "Max loop iterations",
|
||||||
},
|
},
|
||||||
failure: {
|
failure: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Failure Condition",
|
title: "Failure Condition",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -33,20 +39,20 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
items: {
|
items: {
|
||||||
customType: "item",
|
customType: AutomationCustomIOType.ITEM,
|
||||||
description: "The item currently being executed",
|
description: "The item currently being executed",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the message loop was successfully",
|
description: "Whether the message loop was successfully",
|
||||||
},
|
},
|
||||||
iterations: {
|
iterations: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
descriptions: "The amount of times the block ran",
|
description: "The amount of times the block ran",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["success", "items", "iterations"],
|
required: ["success", "items", "iterations"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "LOGIC",
|
type: AutomationStepType.LOGIC,
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,11 @@ import { getFetchResponse } from "./utils"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
enum RequestType {
|
enum RequestType {
|
||||||
|
@ -27,7 +30,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Send a {{inputs.requestMethod}} request",
|
tagline: "Send a {{inputs.requestMethod}} request",
|
||||||
icon: "Send",
|
icon: "Send",
|
||||||
description: "Send a request of specified method to a URL",
|
description: "Send a request of specified method to a URL",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.OUTGOING_WEBHOOK,
|
stepId: AutomationActionStepId.OUTGOING_WEBHOOK,
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -40,23 +43,23 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
requestMethod: {
|
requestMethod: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
enum: Object.values(RequestType),
|
enum: Object.values(RequestType),
|
||||||
title: "Request method",
|
title: "Request method",
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "URL",
|
title: "URL",
|
||||||
},
|
},
|
||||||
requestBody: {
|
requestBody: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "JSON Body",
|
title: "JSON Body",
|
||||||
customType: "wide",
|
customType: AutomationCustomIOType.WIDE,
|
||||||
},
|
},
|
||||||
headers: {
|
headers: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Headers",
|
title: "Headers",
|
||||||
customType: "wide",
|
customType: AutomationCustomIOType.WIDE,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["requestMethod", "url"],
|
required: ["requestMethod", "url"],
|
||||||
|
@ -64,15 +67,15 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The response from the webhook",
|
description: "The response from the webhook",
|
||||||
},
|
},
|
||||||
httpStatus: {
|
httpStatus: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "The HTTP status code returned",
|
description: "The HTTP status code returned",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -5,8 +5,11 @@ import { buildCtx } from "./utils"
|
||||||
import * as automationUtils from "../automationUtils"
|
import * as automationUtils from "../automationUtils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
Table,
|
Table,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -36,7 +39,7 @@ export const definition: AutomationStepSchema = {
|
||||||
icon: "Search",
|
icon: "Search",
|
||||||
name: "Query rows",
|
name: "Query rows",
|
||||||
tagline: "Query rows from {{inputs.enriched.table.name}} table",
|
tagline: "Query rows from {{inputs.enriched.table.name}} table",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
stepId: AutomationActionStepId.QUERY_ROWS,
|
stepId: AutomationActionStepId.QUERY_ROWS,
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -44,35 +47,35 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
filters: {
|
filters: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "filters",
|
customType: AutomationCustomIOType.FILTERS,
|
||||||
title: "Filtering",
|
title: "Filtering",
|
||||||
},
|
},
|
||||||
sortColumn: {
|
sortColumn: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Sort Column",
|
title: "Sort Column",
|
||||||
customType: "column",
|
customType: AutomationCustomIOType.COLUMN,
|
||||||
},
|
},
|
||||||
sortOrder: {
|
sortOrder: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Sort Order",
|
title: "Sort Order",
|
||||||
enum: Object.values(SortOrder),
|
enum: Object.values(SortOrder),
|
||||||
pretty: Object.values(SortOrderPretty),
|
pretty: Object.values(SortOrderPretty),
|
||||||
},
|
},
|
||||||
limit: {
|
limit: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
title: "Limit",
|
title: "Limit",
|
||||||
customType: "queryLimit",
|
customType: AutomationCustomIOType.QUERY_LIMIT,
|
||||||
},
|
},
|
||||||
onEmptyFilter: {
|
onEmptyFilter: {
|
||||||
pretty: Object.values(EmptyFilterOptionPretty),
|
pretty: Object.values(EmptyFilterOptionPretty),
|
||||||
enum: Object.values(EmptyFilterOption),
|
enum: Object.values(EmptyFilterOption),
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "When Filter Empty",
|
title: "When Filter Empty",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -81,12 +84,12 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
rows: {
|
rows: {
|
||||||
type: "array",
|
type: AutomationIOType.ARRAY,
|
||||||
customType: "rows",
|
customType: AutomationCustomIOType.ROWS,
|
||||||
description: "The rows that were found",
|
description: "The rows that were found",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the query was successful",
|
description: "Whether the query was successful",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -11,7 +13,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Send SMTP email to {{inputs.to}}",
|
tagline: "Send SMTP email to {{inputs.to}}",
|
||||||
icon: "Email",
|
icon: "Email",
|
||||||
name: "Send Email (SMTP)",
|
name: "Send Email (SMTP)",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.SEND_EMAIL_SMTP,
|
stepId: AutomationActionStepId.SEND_EMAIL_SMTP,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -19,27 +21,27 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
to: {
|
to: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Send To",
|
title: "Send To",
|
||||||
},
|
},
|
||||||
from: {
|
from: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Send From",
|
title: "Send From",
|
||||||
},
|
},
|
||||||
cc: {
|
cc: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "CC",
|
title: "CC",
|
||||||
},
|
},
|
||||||
bcc: {
|
bcc: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "BCC",
|
title: "BCC",
|
||||||
},
|
},
|
||||||
subject: {
|
subject: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Email Subject",
|
title: "Email Subject",
|
||||||
},
|
},
|
||||||
contents: {
|
contents: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "HTML Contents",
|
title: "HTML Contents",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -48,11 +50,11 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the email was sent",
|
description: "Whether the email was sent",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "A response from the email client, this may be an error",
|
description: "A response from the email client, this may be an error",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -2,6 +2,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,7 +17,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Console log a value in the backend",
|
tagline: "Console log a value in the backend",
|
||||||
icon: "Monitoring",
|
icon: "Monitoring",
|
||||||
description: "Logs the given text to the server (using console.log)",
|
description: "Logs the given text to the server (using console.log)",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.SERVER_LOG,
|
stepId: AutomationActionStepId.SERVER_LOG,
|
||||||
inputs: {
|
inputs: {
|
||||||
|
@ -25,7 +27,7 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
text: {
|
text: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Log",
|
title: "Log",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -34,11 +36,11 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
message: {
|
message: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "What was output",
|
description: "What was output",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,6 +4,8 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,18 +14,18 @@ export const definition: AutomationStepSchema = {
|
||||||
description: "Send a message to Slack",
|
description: "Send a message to Slack",
|
||||||
icon: "ri-slack-line",
|
icon: "ri-slack-line",
|
||||||
stepId: AutomationActionStepId.slack,
|
stepId: AutomationActionStepId.slack,
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: false,
|
internal: false,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
url: {
|
url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Incoming Webhook URL",
|
title: "Incoming Webhook URL",
|
||||||
},
|
},
|
||||||
text: {
|
text: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Message",
|
title: "Message",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -32,15 +34,15 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
httpStatus: {
|
httpStatus: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "The HTTP status code of the request",
|
description: "The HTTP status code of the request",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the message sent successfully",
|
description: "Whether the message sent successfully",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The response from the Slack Webhook",
|
description: "The response from the Slack Webhook",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,8 +3,11 @@ import * as automationUtils from "../automationUtils"
|
||||||
import { buildCtx } from "./utils"
|
import { buildCtx } from "./utils"
|
||||||
import {
|
import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepSchema,
|
||||||
|
AutomationStepType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
|
@ -12,7 +15,7 @@ export const definition: AutomationStepSchema = {
|
||||||
tagline: "Update a {{inputs.enriched.table.name}} row",
|
tagline: "Update a {{inputs.enriched.table.name}} row",
|
||||||
icon: "Refresh",
|
icon: "Refresh",
|
||||||
description: "Update a row in your database",
|
description: "Update a row in your database",
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: true,
|
internal: true,
|
||||||
stepId: AutomationActionStepId.UPDATE_ROW,
|
stepId: AutomationActionStepId.UPDATE_ROW,
|
||||||
inputs: {},
|
inputs: {},
|
||||||
|
@ -20,16 +23,16 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
meta: {
|
meta: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
title: "Field settings",
|
title: "Field settings",
|
||||||
},
|
},
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
rowId: {
|
rowId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Row ID",
|
title: "Row ID",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -38,24 +41,24 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The updated row",
|
description: "The updated row",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "The response from the table",
|
description: "The response from the table",
|
||||||
},
|
},
|
||||||
success: {
|
success: {
|
||||||
type: "boolean",
|
type: AutomationIOType.BOOLEAN,
|
||||||
description: "Whether the action was successful",
|
description: "Whether the action was successful",
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The identifier of the updated row",
|
description: "The identifier of the updated row",
|
||||||
},
|
},
|
||||||
revision: {
|
revision: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The revision of the updated row",
|
description: "The revision of the updated row",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -4,12 +4,14 @@ import {
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
AutomationStepSchema,
|
AutomationStepSchema,
|
||||||
AutomationStepInput,
|
AutomationStepInput,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationIOType,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
export const definition: AutomationStepSchema = {
|
export const definition: AutomationStepSchema = {
|
||||||
name: "Zapier Webhook",
|
name: "Zapier Webhook",
|
||||||
stepId: AutomationActionStepId.zapier,
|
stepId: AutomationActionStepId.zapier,
|
||||||
type: "ACTION",
|
type: AutomationStepType.ACTION,
|
||||||
internal: false,
|
internal: false,
|
||||||
description: "Trigger a Zapier Zap via webhooks",
|
description: "Trigger a Zapier Zap via webhooks",
|
||||||
tagline: "Trigger a Zapier Zap",
|
tagline: "Trigger a Zapier Zap",
|
||||||
|
@ -19,27 +21,27 @@ export const definition: AutomationStepSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
url: {
|
url: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Webhook URL",
|
title: "Webhook URL",
|
||||||
},
|
},
|
||||||
value1: {
|
value1: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Payload Value 1",
|
title: "Payload Value 1",
|
||||||
},
|
},
|
||||||
value2: {
|
value2: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Payload Value 2",
|
title: "Payload Value 2",
|
||||||
},
|
},
|
||||||
value3: {
|
value3: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Payload Value 3",
|
title: "Payload Value 3",
|
||||||
},
|
},
|
||||||
value4: {
|
value4: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Payload Value 4",
|
title: "Payload Value 4",
|
||||||
},
|
},
|
||||||
value5: {
|
value5: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
title: "Payload Value 5",
|
title: "Payload Value 5",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -48,11 +50,11 @@ export const definition: AutomationStepSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
httpStatus: {
|
httpStatus: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "The HTTP status code of the request",
|
description: "The HTTP status code of the request",
|
||||||
},
|
},
|
||||||
response: {
|
response: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "The response from Zapier",
|
description: "The response from Zapier",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import TestConfig from "../../../tests/utilities/TestConfiguration"
|
import TestConfig from "../../../tests/utilities/TestConfiguration"
|
||||||
import { context } from "@budibase/backend-core"
|
import { context } from "@budibase/backend-core"
|
||||||
import { ACTION_DEFINITIONS, getAction } from "../../actions"
|
import { BUILTIN_ACTION_DEFINITIONS, getAction } from "../../actions"
|
||||||
import emitter from "../../../events/index"
|
import emitter from "../../../events/index"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
|
|
||||||
|
@ -57,4 +57,4 @@ export async function runStep(stepId: string, inputs: any, stepContext?: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export const apiKey = "test"
|
export const apiKey = "test"
|
||||||
export const actions = ACTION_DEFINITIONS
|
export const actions = BUILTIN_ACTION_DEFINITIONS
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
fields: {
|
fields: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "triggerSchema",
|
customType: AutomationCustomIOType.TRIGGER_SCHEMA,
|
||||||
title: "Fields",
|
title: "Fields",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,13 +28,13 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
fields: {
|
fields: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "Fields submitted from the app frontend",
|
description: "Fields submitted from the app frontend",
|
||||||
customType: "triggerSchema",
|
customType: AutomationCustomIOType.TRIGGER_SCHEMA,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["fields"],
|
required: ["fields"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
cron: {
|
cron: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "cron",
|
customType: AutomationCustomIOType.CRON,
|
||||||
title: "Expression",
|
title: "Expression",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,12 +28,12 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
timestamp: {
|
timestamp: {
|
||||||
type: "number",
|
type: AutomationIOType.NUMBER,
|
||||||
description: "Timestamp the cron was executed",
|
description: "Timestamp the cron was executed",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["timestamp"],
|
required: ["timestamp"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,13 +28,13 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The row that was deleted",
|
description: "The row that was deleted",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["row"],
|
required: ["row"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,21 +28,21 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The new row that was created",
|
description: "The new row that was created",
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "Row ID - can be used for updating",
|
description: "Row ID - can be used for updating",
|
||||||
},
|
},
|
||||||
revision: {
|
revision: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "Revision of row",
|
description: "Revision of row",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["row", "id"],
|
required: ["row", "id"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,8 +18,8 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
tableId: {
|
tableId: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "table",
|
customType: AutomationCustomIOType.TABLE,
|
||||||
title: "Table",
|
title: "Table",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -25,21 +28,21 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
row: {
|
row: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
customType: "row",
|
customType: AutomationCustomIOType.ROW,
|
||||||
description: "The row that was updated",
|
description: "The row that was updated",
|
||||||
},
|
},
|
||||||
id: {
|
id: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "Row ID - can be used for updating",
|
description: "Row ID - can be used for updating",
|
||||||
},
|
},
|
||||||
revision: {
|
revision: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
description: "Revision of row",
|
description: "Revision of row",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["row", "id"],
|
required: ["row", "id"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
import {
|
import {
|
||||||
|
AutomationCustomIOType,
|
||||||
|
AutomationIOType,
|
||||||
|
AutomationStepType,
|
||||||
AutomationTriggerSchema,
|
AutomationTriggerSchema,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
@ -15,13 +18,13 @@ export const definition: AutomationTriggerSchema = {
|
||||||
inputs: {
|
inputs: {
|
||||||
properties: {
|
properties: {
|
||||||
schemaUrl: {
|
schemaUrl: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "webhookUrl",
|
customType: AutomationCustomIOType.WEBHOOK_URL,
|
||||||
title: "Schema URL",
|
title: "Schema URL",
|
||||||
},
|
},
|
||||||
triggerUrl: {
|
triggerUrl: {
|
||||||
type: "string",
|
type: AutomationIOType.STRING,
|
||||||
customType: "webhookUrl",
|
customType: AutomationCustomIOType.WEBHOOK_URL,
|
||||||
title: "Trigger URL",
|
title: "Trigger URL",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -30,12 +33,12 @@ export const definition: AutomationTriggerSchema = {
|
||||||
outputs: {
|
outputs: {
|
||||||
properties: {
|
properties: {
|
||||||
body: {
|
body: {
|
||||||
type: "object",
|
type: AutomationIOType.OBJECT,
|
||||||
description: "Body of the request which hit the webhook",
|
description: "Body of the request which hit the webhook",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ["body"],
|
required: ["body"],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
type: "TRIGGER",
|
type: AutomationStepType.TRIGGER,
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,11 +14,11 @@ import firebase from "./firebase"
|
||||||
import redis from "./redis"
|
import redis from "./redis"
|
||||||
import snowflake from "./snowflake"
|
import snowflake from "./snowflake"
|
||||||
import oracle from "./oracle"
|
import oracle from "./oracle"
|
||||||
import { getPlugins } from "../api/controllers/plugin"
|
|
||||||
import { SourceName, Integration, PluginType } from "@budibase/types"
|
import { SourceName, Integration, PluginType } from "@budibase/types"
|
||||||
import { getDatasourcePlugin } from "../utilities/fileSystem"
|
import { getDatasourcePlugin } from "../utilities/fileSystem"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
import { cloneDeep } from "lodash"
|
import { cloneDeep } from "lodash"
|
||||||
|
import sdk from "../sdk"
|
||||||
|
|
||||||
const DEFINITIONS: { [key: string]: Integration } = {
|
const DEFINITIONS: { [key: string]: Integration } = {
|
||||||
[SourceName.POSTGRES]: postgres.schema,
|
[SourceName.POSTGRES]: postgres.schema,
|
||||||
|
@ -79,7 +79,7 @@ export async function getDefinition(source: SourceName): Promise<Integration> {
|
||||||
export async function getDefinitions() {
|
export async function getDefinitions() {
|
||||||
const pluginSchemas: { [key: string]: Integration } = {}
|
const pluginSchemas: { [key: string]: Integration } = {}
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const plugins = await getPlugins(PluginType.DATASOURCE)
|
const plugins = await sdk.plugins.fetch(PluginType.DATASOURCE)
|
||||||
// extract the actual schema from each custom
|
// extract the actual schema from each custom
|
||||||
for (let plugin of plugins) {
|
for (let plugin of plugins) {
|
||||||
const sourceId = plugin.name
|
const sourceId = plugin.name
|
||||||
|
@ -103,7 +103,7 @@ export async function getIntegration(integration: string) {
|
||||||
return INTEGRATIONS[integration]
|
return INTEGRATIONS[integration]
|
||||||
}
|
}
|
||||||
if (env.SELF_HOSTED) {
|
if (env.SELF_HOSTED) {
|
||||||
const plugins = await getPlugins(PluginType.DATASOURCE)
|
const plugins = await sdk.plugins.fetch(PluginType.DATASOURCE)
|
||||||
for (let plugin of plugins) {
|
for (let plugin of plugins) {
|
||||||
if (plugin.name === integration) {
|
if (plugin.name === integration) {
|
||||||
// need to use commonJS require due to its dynamic runtime nature
|
// need to use commonJS require due to its dynamic runtime nature
|
||||||
|
|
|
@ -6,6 +6,7 @@ import { default as datasources } from "./app/datasources"
|
||||||
import { default as queries } from "./app/queries"
|
import { default as queries } from "./app/queries"
|
||||||
import { default as rows } from "./app/rows"
|
import { default as rows } from "./app/rows"
|
||||||
import { default as users } from "./users"
|
import { default as users } from "./users"
|
||||||
|
import { default as plugins } from "./plugins"
|
||||||
|
|
||||||
const sdk = {
|
const sdk = {
|
||||||
backups,
|
backups,
|
||||||
|
@ -16,6 +17,7 @@ const sdk = {
|
||||||
users,
|
users,
|
||||||
datasources,
|
datasources,
|
||||||
queries,
|
queries,
|
||||||
|
plugins,
|
||||||
}
|
}
|
||||||
|
|
||||||
// default export for TS
|
// default export for TS
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
import * as plugins from "./plugins"
|
||||||
|
|
||||||
|
export default {
|
||||||
|
...plugins,
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
import { FileType, Plugin, PluginSource, PluginType } from "@budibase/types"
|
||||||
|
import {
|
||||||
|
db as dbCore,
|
||||||
|
objectStore,
|
||||||
|
plugins as pluginCore,
|
||||||
|
tenancy,
|
||||||
|
} from "@budibase/backend-core"
|
||||||
|
import { fileUpload } from "../../api/controllers/plugin/file"
|
||||||
|
import env from "../../environment"
|
||||||
|
import { ClientAppSocket } from "../../websocket"
|
||||||
|
import { sdk as pro } from "@budibase/pro"
|
||||||
|
|
||||||
|
export async function fetch(type?: PluginType) {
|
||||||
|
const db = tenancy.getGlobalDB()
|
||||||
|
const response = await db.allDocs(
|
||||||
|
dbCore.getPluginParams(null, {
|
||||||
|
include_docs: true,
|
||||||
|
})
|
||||||
|
)
|
||||||
|
let plugins = response.rows.map((row: any) => row.doc) as Plugin[]
|
||||||
|
plugins = objectStore.enrichPluginURLs(plugins)
|
||||||
|
if (type) {
|
||||||
|
return plugins.filter((plugin: Plugin) => plugin.schema?.type === type)
|
||||||
|
} else {
|
||||||
|
return plugins
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function processUploaded(plugin: FileType, source?: PluginSource) {
|
||||||
|
const { metadata, directory } = await fileUpload(plugin)
|
||||||
|
pluginCore.validate(metadata?.schema)
|
||||||
|
|
||||||
|
// Only allow components in cloud
|
||||||
|
if (!env.SELF_HOSTED && metadata?.schema?.type !== PluginType.COMPONENT) {
|
||||||
|
throw new Error("Only component plugins are supported outside of self-host")
|
||||||
|
}
|
||||||
|
|
||||||
|
const doc = await pro.plugins.storePlugin(metadata, directory, source)
|
||||||
|
ClientAppSocket.emit("plugin-update", { name: doc.name, hash: doc.hash })
|
||||||
|
return doc
|
||||||
|
}
|
|
@ -1,18 +1,22 @@
|
||||||
import { permissions, roles } from "@budibase/backend-core"
|
import { permissions, roles, utils } from "@budibase/backend-core"
|
||||||
import { createHomeScreen } from "../../constants/screens"
|
import { createHomeScreen } from "../../constants/screens"
|
||||||
import { EMPTY_LAYOUT } from "../../constants/layouts"
|
import { EMPTY_LAYOUT } from "../../constants/layouts"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import { ACTION_DEFINITIONS, TRIGGER_DEFINITIONS } from "../../automations"
|
import {
|
||||||
|
BUILTIN_ACTION_DEFINITIONS,
|
||||||
|
TRIGGER_DEFINITIONS,
|
||||||
|
} from "../../automations"
|
||||||
import {
|
import {
|
||||||
Automation,
|
Automation,
|
||||||
AutomationActionStepId,
|
AutomationActionStepId,
|
||||||
|
AutomationStep,
|
||||||
|
AutomationStepType,
|
||||||
|
AutomationTrigger,
|
||||||
AutomationTriggerStepId,
|
AutomationTriggerStepId,
|
||||||
Datasource,
|
Datasource,
|
||||||
SourceName,
|
SourceName,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
|
|
||||||
const { v4: uuidv4 } = require("uuid")
|
|
||||||
|
|
||||||
export function basicTable() {
|
export function basicTable() {
|
||||||
return {
|
return {
|
||||||
name: "TestTable",
|
name: "TestTable",
|
||||||
|
@ -71,19 +75,19 @@ export function view(tableId: string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function automationStep(
|
export function automationStep(
|
||||||
actionDefinition = ACTION_DEFINITIONS.CREATE_ROW
|
actionDefinition = BUILTIN_ACTION_DEFINITIONS.CREATE_ROW
|
||||||
) {
|
): AutomationStep {
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
id: utils.newid(),
|
||||||
...actionDefinition,
|
...actionDefinition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function automationTrigger(
|
export function automationTrigger(
|
||||||
triggerDefinition = TRIGGER_DEFINITIONS.ROW_SAVED
|
triggerDefinition = TRIGGER_DEFINITIONS.ROW_SAVED
|
||||||
) {
|
): AutomationTrigger {
|
||||||
return {
|
return {
|
||||||
id: uuidv4(),
|
id: utils.newid(),
|
||||||
...triggerDefinition,
|
...triggerDefinition,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,7 +110,7 @@ export function newAutomation({ steps, trigger }: any = {}) {
|
||||||
return automation
|
return automation
|
||||||
}
|
}
|
||||||
|
|
||||||
export function basicAutomation(appId?: string) {
|
export function basicAutomation(appId?: string): Automation {
|
||||||
return {
|
return {
|
||||||
name: "My Automation",
|
name: "My Automation",
|
||||||
screenId: "kasdkfldsafkl",
|
screenId: "kasdkfldsafkl",
|
||||||
|
@ -119,18 +123,22 @@ export function basicAutomation(appId?: string) {
|
||||||
tagline: "test",
|
tagline: "test",
|
||||||
icon: "test",
|
icon: "test",
|
||||||
description: "test",
|
description: "test",
|
||||||
type: "trigger",
|
type: AutomationStepType.TRIGGER,
|
||||||
id: "test",
|
id: "test",
|
||||||
inputs: {},
|
inputs: {},
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {},
|
inputs: {
|
||||||
outputs: {},
|
properties: {},
|
||||||
|
},
|
||||||
|
outputs: {
|
||||||
|
properties: {},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
steps: [],
|
steps: [],
|
||||||
},
|
},
|
||||||
type: "automation",
|
type: "automation",
|
||||||
appId,
|
appId: appId!,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -154,7 +162,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
|
||||||
inputs: {
|
inputs: {
|
||||||
tableId,
|
tableId,
|
||||||
},
|
},
|
||||||
schema: ACTION_DEFINITIONS.QUERY_ROWS.schema,
|
schema: BUILTIN_ACTION_DEFINITIONS.QUERY_ROWS.schema,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "c",
|
id: "c",
|
||||||
|
@ -163,7 +171,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
|
||||||
internal: true,
|
internal: true,
|
||||||
inputs: loopOpts,
|
inputs: loopOpts,
|
||||||
blockToLoop: "d",
|
blockToLoop: "d",
|
||||||
schema: ACTION_DEFINITIONS.LOOP.schema,
|
schema: BUILTIN_ACTION_DEFINITIONS.LOOP.schema,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "d",
|
id: "d",
|
||||||
|
@ -173,7 +181,7 @@ export function loopAutomation(tableId: string, loopOpts?: any): Automation {
|
||||||
inputs: {
|
inputs: {
|
||||||
text: "log statement",
|
text: "log statement",
|
||||||
},
|
},
|
||||||
schema: ACTION_DEFINITIONS.SERVER_LOG.schema,
|
schema: BUILTIN_ACTION_DEFINITIONS.SERVER_LOG.schema,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
trigger: {
|
trigger: {
|
||||||
|
|
|
@ -27,8 +27,8 @@ import { processObject } from "@budibase/string-templates"
|
||||||
import { cloneDeep } from "lodash/fp"
|
import { cloneDeep } from "lodash/fp"
|
||||||
import * as sdkUtils from "../sdk/utils"
|
import * as sdkUtils from "../sdk/utils"
|
||||||
import env from "../environment"
|
import env from "../environment"
|
||||||
const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId
|
const FILTER_STEP_ID = actions.BUILTIN_ACTION_DEFINITIONS.FILTER.stepId
|
||||||
const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId
|
const LOOP_STEP_ID = actions.BUILTIN_ACTION_DEFINITIONS.LOOP.stepId
|
||||||
const CRON_STEP_ID = triggerDefs.CRON.stepId
|
const CRON_STEP_ID = triggerDefs.CRON.stepId
|
||||||
const STOPPED_STATUS = { success: true, status: AutomationStatus.STOPPED }
|
const STOPPED_STATUS = { success: true, status: AutomationStatus.STOPPED }
|
||||||
|
|
||||||
|
|
|
@ -5,6 +5,7 @@ import { join } from "path"
|
||||||
import { objectStore } from "@budibase/backend-core"
|
import { objectStore } from "@budibase/backend-core"
|
||||||
|
|
||||||
const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
const DATASOURCE_PATH = join(budibaseTempDir(), "datasource")
|
||||||
|
const AUTOMATION_PATH = join(budibaseTempDir(), "automation")
|
||||||
|
|
||||||
export const getPluginMetadata = async (path: string) => {
|
export const getPluginMetadata = async (path: string) => {
|
||||||
let metadata: any = {}
|
let metadata: any = {}
|
||||||
|
@ -33,12 +34,12 @@ export const getPluginMetadata = async (path: string) => {
|
||||||
return { metadata, directory: path }
|
return { metadata, directory: path }
|
||||||
}
|
}
|
||||||
|
|
||||||
export const getDatasourcePlugin = async (plugin: Plugin) => {
|
async function getPluginImpl(path: string, plugin: Plugin) {
|
||||||
const hash = plugin.schema?.hash
|
const hash = plugin.schema?.hash
|
||||||
if (!fs.existsSync(DATASOURCE_PATH)) {
|
if (!fs.existsSync(path)) {
|
||||||
fs.mkdirSync(DATASOURCE_PATH)
|
fs.mkdirSync(path)
|
||||||
}
|
}
|
||||||
const filename = join(DATASOURCE_PATH, plugin.name)
|
const filename = join(path, plugin.name)
|
||||||
const metadataName = `${filename}.bbmetadata`
|
const metadataName = `${filename}.bbmetadata`
|
||||||
if (fs.existsSync(filename)) {
|
if (fs.existsSync(filename)) {
|
||||||
const currentHash = fs.readFileSync(metadataName, "utf8")
|
const currentHash = fs.readFileSync(metadataName, "utf8")
|
||||||
|
@ -62,3 +63,11 @@ export const getDatasourcePlugin = async (plugin: Plugin) => {
|
||||||
|
|
||||||
return require(filename)
|
return require(filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const getDatasourcePlugin = async (plugin: Plugin) => {
|
||||||
|
return getPluginImpl(DATASOURCE_PATH, plugin)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const getAutomationPlugin = async (plugin: Plugin) => {
|
||||||
|
return getPluginImpl(AUTOMATION_PATH, plugin)
|
||||||
|
}
|
||||||
|
|
|
@ -3,7 +3,7 @@ import env from "./environment"
|
||||||
import chokidar from "chokidar"
|
import chokidar from "chokidar"
|
||||||
import fs from "fs"
|
import fs from "fs"
|
||||||
import { constants, tenancy } from "@budibase/backend-core"
|
import { constants, tenancy } from "@budibase/backend-core"
|
||||||
import { processUploadedPlugin } from "./api/controllers/plugin"
|
import pluginsSdk from "./sdk/plugins"
|
||||||
|
|
||||||
export function watch() {
|
export function watch() {
|
||||||
const watchPath = path.join(env.PLUGINS_DIR, "./**/*.tar.gz")
|
const watchPath = path.join(env.PLUGINS_DIR, "./**/*.tar.gz")
|
||||||
|
@ -27,7 +27,7 @@ export function watch() {
|
||||||
const split = path.split("/")
|
const split = path.split("/")
|
||||||
const name = split[split.length - 1]
|
const name = split[split.length - 1]
|
||||||
console.log("Importing plugin:", path)
|
console.log("Importing plugin:", path)
|
||||||
await processUploadedPlugin({ name, path })
|
await pluginsSdk.processUploaded({ name, path })
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
const message = err?.message ? err?.message : err
|
const message = err?.message ? err?.message : err
|
||||||
console.error("Failed to import plugin:", message)
|
console.error("Failed to import plugin:", message)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/shared-core",
|
"name": "@budibase/shared-core",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Shared data utils",
|
"description": "Shared data utils",
|
||||||
"main": "dist/cjs/src/index.js",
|
"main": "dist/cjs/src/index.js",
|
||||||
"types": "dist/mjs/src/index.d.ts",
|
"types": "dist/mjs/src/index.d.ts",
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
|
"dev:builder": "yarn prebuild && concurrently \"tsc -p tsconfig.build.json --watch\" \"tsc -p tsconfig-cjs.build.json --watch\""
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/types": "2.5.6-alpha.3"
|
"@budibase/types": "2.5.6-alpha.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"concurrently": "^7.6.0",
|
"concurrently": "^7.6.0",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/types",
|
"name": "@budibase/types",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase types",
|
"description": "Budibase types",
|
||||||
"main": "dist/cjs/index.js",
|
"main": "dist/cjs/index.js",
|
||||||
"types": "dist/mjs/index.d.ts",
|
"types": "dist/mjs/index.d.ts",
|
||||||
|
|
|
@ -1,6 +1,32 @@
|
||||||
import { Document } from "../document"
|
import { Document } from "../document"
|
||||||
import { EventEmitter } from "events"
|
import { EventEmitter } from "events"
|
||||||
|
|
||||||
|
export enum AutomationIOType {
|
||||||
|
OBJECT = "object",
|
||||||
|
STRING = "string",
|
||||||
|
BOOLEAN = "boolean",
|
||||||
|
NUMBER = "number",
|
||||||
|
ARRAY = "array",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AutomationCustomIOType {
|
||||||
|
TABLE = "table",
|
||||||
|
ROW = "row",
|
||||||
|
ROWS = "rows",
|
||||||
|
WIDE = "wide",
|
||||||
|
QUERY = "query",
|
||||||
|
QUERY_PARAMS = "queryParams",
|
||||||
|
QUERY_LIMIT = "queryLimit",
|
||||||
|
LOOP_OPTION = "loopOption",
|
||||||
|
ITEM = "item",
|
||||||
|
CODE = "code",
|
||||||
|
FILTERS = "filters",
|
||||||
|
COLUMN = "column",
|
||||||
|
TRIGGER_SCHEMA = "triggerSchema",
|
||||||
|
CRON = "cron",
|
||||||
|
WEBHOOK_URL = "webhookUrl",
|
||||||
|
}
|
||||||
|
|
||||||
export enum AutomationTriggerStepId {
|
export enum AutomationTriggerStepId {
|
||||||
ROW_SAVED = "ROW_SAVED",
|
ROW_SAVED = "ROW_SAVED",
|
||||||
ROW_UPDATED = "ROW_UPDATED",
|
ROW_UPDATED = "ROW_UPDATED",
|
||||||
|
@ -10,6 +36,12 @@ export enum AutomationTriggerStepId {
|
||||||
CRON = "CRON",
|
CRON = "CRON",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AutomationStepType {
|
||||||
|
LOGIC = "LOGIC",
|
||||||
|
ACTION = "ACTION",
|
||||||
|
TRIGGER = "TRIGGER",
|
||||||
|
}
|
||||||
|
|
||||||
export enum AutomationActionStepId {
|
export enum AutomationActionStepId {
|
||||||
SEND_EMAIL_SMTP = "SEND_EMAIL_SMTP",
|
SEND_EMAIL_SMTP = "SEND_EMAIL_SMTP",
|
||||||
CREATE_ROW = "CREATE_ROW",
|
CREATE_ROW = "CREATE_ROW",
|
||||||
|
@ -31,14 +63,43 @@ export enum AutomationActionStepId {
|
||||||
integromat = "integromat",
|
integromat = "integromat",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const AutomationStepIdArray = [
|
||||||
|
...Object.values(AutomationActionStepId),
|
||||||
|
...Object.values(AutomationTriggerStepId),
|
||||||
|
]
|
||||||
|
|
||||||
export interface Automation extends Document {
|
export interface Automation extends Document {
|
||||||
definition: {
|
definition: {
|
||||||
steps: AutomationStep[]
|
steps: AutomationStep[]
|
||||||
trigger: AutomationTrigger
|
trigger: AutomationTrigger
|
||||||
}
|
}
|
||||||
|
screenId?: string
|
||||||
|
uiTree?: any
|
||||||
appId: string
|
appId: string
|
||||||
live?: boolean
|
live?: boolean
|
||||||
name: string
|
name: string
|
||||||
|
internal?: boolean
|
||||||
|
type?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BaseIOStructure {
|
||||||
|
type?: AutomationIOType
|
||||||
|
customType?: AutomationCustomIOType
|
||||||
|
title?: string
|
||||||
|
description?: string
|
||||||
|
enum?: string[]
|
||||||
|
pretty?: string[]
|
||||||
|
properties?: {
|
||||||
|
[key: string]: BaseIOStructure
|
||||||
|
}
|
||||||
|
required?: string[]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface InputOutputBlock {
|
||||||
|
properties: {
|
||||||
|
[key: string]: BaseIOStructure
|
||||||
|
}
|
||||||
|
required?: string[]
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationStepSchema {
|
export interface AutomationStepSchema {
|
||||||
|
@ -46,7 +107,7 @@ export interface AutomationStepSchema {
|
||||||
tagline: string
|
tagline: string
|
||||||
icon: string
|
icon: string
|
||||||
description: string
|
description: string
|
||||||
type: string
|
type: AutomationStepType
|
||||||
internal?: boolean
|
internal?: boolean
|
||||||
deprecated?: boolean
|
deprecated?: boolean
|
||||||
stepId: AutomationTriggerStepId | AutomationActionStepId
|
stepId: AutomationTriggerStepId | AutomationActionStepId
|
||||||
|
@ -55,14 +116,10 @@ export interface AutomationStepSchema {
|
||||||
[key: string]: any
|
[key: string]: any
|
||||||
}
|
}
|
||||||
schema: {
|
schema: {
|
||||||
inputs: {
|
inputs: InputOutputBlock
|
||||||
[key: string]: any
|
outputs: InputOutputBlock
|
||||||
}
|
|
||||||
outputs: {
|
|
||||||
[key: string]: any
|
|
||||||
}
|
|
||||||
required?: string[]
|
|
||||||
}
|
}
|
||||||
|
custom?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutomationStep extends AutomationStepSchema {
|
export interface AutomationStep extends AutomationStepSchema {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import { Document } from "../document"
|
||||||
export enum PluginType {
|
export enum PluginType {
|
||||||
DATASOURCE = "datasource",
|
DATASOURCE = "datasource",
|
||||||
COMPONENT = "component",
|
COMPONENT = "component",
|
||||||
|
AUTOMATION = "automation",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum PluginSource {
|
export enum PluginSource {
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "2.5.6-alpha.3",
|
"version": "2.5.6-alpha.5",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -37,10 +37,10 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "2.5.6-alpha.3",
|
"@budibase/backend-core": "2.5.6-alpha.5",
|
||||||
"@budibase/pro": "2.5.6-alpha.3",
|
"@budibase/pro": "2.5.6-alpha.5",
|
||||||
"@budibase/string-templates": "2.5.6-alpha.3",
|
"@budibase/string-templates": "2.5.6-alpha.5",
|
||||||
"@budibase/types": "2.5.6-alpha.3",
|
"@budibase/types": "2.5.6-alpha.5",
|
||||||
"@koa/router": "8.0.8",
|
"@koa/router": "8.0.8",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "0.3.2",
|
"@techpass/passport-openidconnect": "0.3.2",
|
||||||
|
|
Loading…
Reference in New Issue