Merge branch 'develop' of github.com:Budibase/budibase into dnd-improvements

This commit is contained in:
Andrew Kingston 2022-10-05 17:31:01 +01:00
commit ee4c5af1c9
40 changed files with 252 additions and 118 deletions

View File

@ -4,6 +4,7 @@ echo ${TARGETBUILD} > /buildtarget.txt
if [[ "${TARGETBUILD}" = "aas" ]]; then if [[ "${TARGETBUILD}" = "aas" ]]; then
# Azure AppService uses /home for persisent data & SSH on port 2222 # Azure AppService uses /home for persisent data & SSH on port 2222
DATA_DIR=/home DATA_DIR=/home
WEBSITES_ENABLE_APP_SERVICE_STORAGE=true
mkdir -p $DATA_DIR/{search,minio,couch} mkdir -p $DATA_DIR/{search,minio,couch}
mkdir -p $DATA_DIR/couch/{dbs,views} mkdir -p $DATA_DIR/couch/{dbs,views}
chown -R couchdb:couchdb $DATA_DIR/couch/ chown -R couchdb:couchdb $DATA_DIR/couch/

View File

@ -21,6 +21,7 @@ declare -a DOCKER_VARS=("APP_PORT" "APPS_URL" "ARCHITECTURE" "BUDIBASE_ENVIRONME
# Azure App Service customisations # Azure App Service customisations
if [[ "${TARGETBUILD}" = "aas" ]]; then if [[ "${TARGETBUILD}" = "aas" ]]; then
DATA_DIR=/home DATA_DIR=/home
WEBSITES_ENABLE_APP_SERVICE_STORAGE=true
/etc/init.d/ssh start /etc/init.d/ssh start
else else
DATA_DIR=${DATA_DIR:-/data} DATA_DIR=${DATA_DIR:-/data}

View File

@ -1,5 +1,5 @@
{ {
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"npmClient": "yarn", "npmClient": "yarn",
"packages": [ "packages": [
"packages/*" "packages/*"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/backend-core", "name": "@budibase/backend-core",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"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",
@ -20,7 +20,7 @@
"test:watch": "jest --watchAll" "test:watch": "jest --watchAll"
}, },
"dependencies": { "dependencies": {
"@budibase/types": "2.0.14-alpha.0", "@budibase/types": "2.0.14-alpha.4",
"@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-sdk": "2.1030.0", "aws-sdk": "2.1030.0",

View File

@ -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.0.14-alpha.0", "version": "2.0.14-alpha.4",
"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,7 +38,7 @@
], ],
"dependencies": { "dependencies": {
"@adobe/spectrum-css-workflow-icons": "^1.2.1", "@adobe/spectrum-css-workflow-icons": "^1.2.1",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@spectrum-css/actionbutton": "^1.0.1", "@spectrum-css/actionbutton": "^1.0.1",
"@spectrum-css/actiongroup": "^1.0.1", "@spectrum-css/actiongroup": "^1.0.1",
"@spectrum-css/avatar": "^3.0.2", "@spectrum-css/avatar": "^3.0.2",

View File

@ -19,6 +19,7 @@
export let placeholderOption = null export let placeholderOption = null
export let options = [] export let options = []
export let isOptionSelected = () => false export let isOptionSelected = () => false
export let isOptionEnabled = () => true
export let onSelectOption = () => {} export let onSelectOption = () => {}
export let getOptionLabel = option => option export let getOptionLabel = option => option
export let getOptionValue = option => option export let getOptionValue = option => option
@ -164,6 +165,7 @@
aria-selected="true" aria-selected="true"
tabindex="0" tabindex="0"
on:click={() => onSelectOption(getOptionValue(option, idx))} on:click={() => onSelectOption(getOptionValue(option, idx))}
class:is-disabled={!isOptionEnabled(option)}
> >
{#if getOptionIcon(option, idx)} {#if getOptionIcon(option, idx)}
<span class="option-extra"> <span class="option-extra">
@ -256,4 +258,7 @@
.spectrum-Popover :global(.spectrum-Search .spectrum-Textfield-icon) { .spectrum-Popover :global(.spectrum-Search .spectrum-Textfield-icon) {
top: 9px; top: 9px;
} }
.spectrum-Menu-item.is-disabled {
pointer-events: none;
}
</style> </style>

View File

@ -12,6 +12,7 @@
export let getOptionValue = option => option export let getOptionValue = option => option
export let getOptionIcon = () => null export let getOptionIcon = () => null
export let getOptionColour = () => null export let getOptionColour = () => null
export let isOptionEnabled
export let readonly = false export let readonly = false
export let quiet = false export let quiet = false
export let autoWidth = false export let autoWidth = false
@ -66,6 +67,7 @@
{getOptionValue} {getOptionValue}
{getOptionIcon} {getOptionIcon}
{getOptionColour} {getOptionColour}
{isOptionEnabled}
{autocomplete} {autocomplete}
{sort} {sort}
isPlaceholder={value == null || value === ""} isPlaceholder={value == null || value === ""}

View File

@ -15,6 +15,7 @@
export let getOptionValue = option => extractProperty(option, "value") export let getOptionValue = option => extractProperty(option, "value")
export let getOptionIcon = option => option?.icon export let getOptionIcon = option => option?.icon
export let getOptionColour = option => option?.colour export let getOptionColour = option => option?.colour
export let isOptionEnabled
export let quiet = false export let quiet = false
export let autoWidth = false export let autoWidth = false
export let sort = false export let sort = false
@ -49,6 +50,7 @@
{getOptionValue} {getOptionValue}
{getOptionIcon} {getOptionIcon}
{getOptionColour} {getOptionColour}
{isOptionEnabled}
on:change={onChange} on:change={onChange}
on:click on:click
/> />

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -71,10 +71,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "2.0.14-alpha.0", "@budibase/bbui": "2.0.14-alpha.4",
"@budibase/client": "2.0.14-alpha.0", "@budibase/client": "2.0.14-alpha.4",
"@budibase/frontend-core": "2.0.14-alpha.0", "@budibase/frontend-core": "2.0.14-alpha.4",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@sentry/browser": "5.19.1", "@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1", "@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1", "@spectrum-css/vars": "^3.0.1",

View File

@ -314,7 +314,7 @@
const relatedTable = $tables.list.find( const relatedTable = $tables.list.find(
tbl => tbl._id === fieldInfo.tableId tbl => tbl._id === fieldInfo.tableId
) )
if (inUse(relatedTable, fieldInfo.fieldName)) { if (inUse(relatedTable, fieldInfo.fieldName) && !originalName) {
newError.relatedName = `Column name already in use in table ${relatedTable.name}` newError.relatedName = `Column name already in use in table ${relatedTable.name}`
} }
} }

View File

@ -1,5 +1,5 @@
<script> <script>
import { Layout, Table, Select, Pagination } from "@budibase/bbui" import { Layout, Table, Select, Pagination, Button } from "@budibase/bbui"
import DateTimeRenderer from "components/common/renderers/DateTimeRenderer.svelte" import DateTimeRenderer from "components/common/renderers/DateTimeRenderer.svelte"
import StatusRenderer from "./StatusRenderer.svelte" import StatusRenderer from "./StatusRenderer.svelte"
import HistoryDetailsPanel from "./HistoryDetailsPanel.svelte" import HistoryDetailsPanel from "./HistoryDetailsPanel.svelte"
@ -7,12 +7,16 @@
import { createPaginationStore } from "helpers/pagination" import { createPaginationStore } from "helpers/pagination"
import { onMount } from "svelte" import { onMount } from "svelte"
import dayjs from "dayjs" import dayjs from "dayjs"
import { auth, licensing, admin } from "stores/portal"
import { Constants } from "@budibase/frontend-core"
const ERROR = "error", const ERROR = "error",
SUCCESS = "success", SUCCESS = "success",
STOPPED = "stopped" STOPPED = "stopped"
export let app export let app
$: licensePlan = $auth.user?.license?.plan
let pageInfo = createPaginationStore() let pageInfo = createPaginationStore()
let runHistory = null let runHistory = null
let showPanel = false let showPanel = false
@ -26,6 +30,8 @@
$: fetchLogs(automationId, status, page, timeRange) $: fetchLogs(automationId, status, page, timeRange)
const timeOptions = [ const timeOptions = [
{ value: "90-d", label: "Past 90 days" },
{ value: "30-d", label: "Past 30 days" },
{ value: "1-w", label: "Past week" }, { value: "1-w", label: "Past week" },
{ value: "1-d", label: "Past day" }, { value: "1-d", label: "Past day" },
{ value: "1-h", label: "Past 1 hour" }, { value: "1-h", label: "Past 1 hour" },
@ -131,10 +137,20 @@
</div> </div>
<div class="select"> <div class="select">
<Select <Select
placeholder="Past 30 days" placeholder="All"
label="Date range" label="Date range"
bind:value={timeRange} bind:value={timeRange}
options={timeOptions} options={timeOptions}
isOptionEnabled={x => {
if (licensePlan?.type === Constants.PlanType.FREE) {
return ["1-w", "30-d", "90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.TEAM) {
return ["90-d"].indexOf(x.value) < 0
} else if (licensePlan?.type === Constants.PlanType.PRO) {
return ["30-d", "90-d"].indexOf(x.value) < 0
}
return true
}}
/> />
</div> </div>
<div class="select"> <div class="select">
@ -145,6 +161,14 @@
options={statusOptions} options={statusOptions}
/> />
</div> </div>
{#if (licensePlan?.type !== Constants.PlanType.ENTERPRISE && $auth.user.accountPortalAccess) || !$admin.cloud}
<div class="pro-upgrade">
<div class="pro-copy">Expand your automation log history</div>
<Button primary newStyles on:click={$licensing.goToUpgradePage()}>
Upgrade
</Button>
</div>
{/if}
</div> </div>
{#if runHistory} {#if runHistory}
<div> <div>
@ -221,4 +245,15 @@
.panelOpen { .panelOpen {
grid-template-columns: auto 420px; grid-template-columns: auto 420px;
} }
.pro-upgrade {
display: flex;
align-items: center;
justify-content: flex-end;
flex: 1;
}
.pro-copy {
margin-right: var(--spacing-l);
}
</style> </style>

View File

@ -58,13 +58,6 @@ export const DefaultAppTheme = {
navTextColor: "var(--spectrum-global-color-gray-800)", navTextColor: "var(--spectrum-global-color-gray-800)",
} }
export const PlanType = {
FREE: "free",
PRO: "pro",
BUSINESS: "business",
ENTERPRISE: "enterprise",
}
export const PluginSource = { export const PluginSource = {
URL: "URL", URL: "URL",
NPM: "NPM", NPM: "NPM",

View File

@ -91,6 +91,7 @@
}) })
</script> </script>
{"is adming" + $auth.isAdmin}
{#if $auth.isAdmin} {#if $auth.isAdmin}
<DeleteLicenseKeyModal <DeleteLicenseKeyModal
bind:this={deleteLicenseKeyModal} bind:this={deleteLicenseKeyModal}

View File

@ -11,7 +11,7 @@
} from "@budibase/bbui" } from "@budibase/bbui"
import { onMount } from "svelte" import { onMount } from "svelte"
import { admin, auth, licensing } from "../../../../stores/portal" import { admin, auth, licensing } from "../../../../stores/portal"
import { PlanType } from "../../../../constants" import { Constants } from "@budibase/frontend-core"
import { DashCard, Usage } from "../../../../components/usage" import { DashCard, Usage } from "../../../../components/usage"
let staticUsage = [] let staticUsage = []
@ -125,7 +125,7 @@
} }
const goToAccountPortal = () => { const goToAccountPortal = () => {
if (license?.plan.type === PlanType.FREE) { if (license?.plan.type === Constants.PlanType.FREE) {
window.location.href = upgradeUrl window.location.href = upgradeUrl
} else { } else {
window.location.href = manageUrl window.location.href = manageUrl
@ -133,7 +133,7 @@
} }
const setPrimaryActionText = () => { const setPrimaryActionText = () => {
if (license?.plan.type === PlanType.FREE) { if (license?.plan.type === Constants.PlanType.FREE) {
primaryActionText = "Upgrade" primaryActionText = "Upgrade"
return return
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"description": "Budibase CLI, for developers, self hosting and migrations.", "description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js", "main": "src/index.js",
"bin": { "bin": {
@ -26,9 +26,9 @@
"outputPath": "build" "outputPath": "build"
}, },
"dependencies": { "dependencies": {
"@budibase/backend-core": "2.0.14-alpha.0", "@budibase/backend-core": "2.0.14-alpha.4",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@budibase/types": "2.0.14-alpha.0", "@budibase/types": "2.0.14-alpha.4",
"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",

View File

@ -22,6 +22,6 @@ exports.runPkgCommand = async (command, dir = "./") => {
throw new Error("Must have yarn or npm installed to run build.") throw new Error("Must have yarn or npm installed to run build.")
} }
const npmCmd = command === "install" ? `npm ${command}` : `npm run ${command}` const npmCmd = command === "install" ? `npm ${command}` : `npm run ${command}`
const cmd = yarn ? `yarn ${command}` : npmCmd const cmd = yarn ? `yarn ${command} --ignore-engines` : npmCmd
await exports.exec(cmd, dir) await exports.exec(cmd, dir)
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"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,9 +19,9 @@
"dev:builder": "rollup -cw" "dev:builder": "rollup -cw"
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "2.0.14-alpha.0", "@budibase/bbui": "2.0.14-alpha.4",
"@budibase/frontend-core": "2.0.14-alpha.0", "@budibase/frontend-core": "2.0.14-alpha.4",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@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",

View File

@ -1,7 +0,0 @@
export const PlanType = {
FREE: "free",
PRO: "pro",
TEAM: "team",
BUSINESS: "business",
ENTERPRISE: "enterprise",
}

View File

@ -1,6 +1,6 @@
import { authStore } from "../stores/auth.js" import { authStore } from "../stores/auth.js"
import { get } from "svelte/store" import { get } from "svelte/store"
import { PlanType } from "./constants" import { Constants } from "@budibase/frontend-core"
const getLicense = () => { const getLicense = () => {
const user = get(authStore) const user = get(authStore)
@ -12,7 +12,7 @@ const getLicense = () => {
export const isFreePlan = () => { export const isFreePlan = () => {
const license = getLicense() const license = getLicense()
if (license) { if (license) {
return license.plan.type === PlanType.FREE return license.plan.type === Constants.PlanType.FREE
} else { } else {
// safety net - no license means free plan // safety net - no license means free plan
return true return true

View File

@ -1,12 +1,12 @@
{ {
"name": "@budibase/frontend-core", "name": "@budibase/frontend-core",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"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.0.14-alpha.0", "@budibase/bbui": "2.0.14-alpha.4",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"svelte": "^3.46.2" "svelte": "^3.46.2"
} }

View File

@ -98,6 +98,7 @@ export const BuilderRoleDescriptions = [
export const PlanType = { export const PlanType = {
FREE: "free", FREE: "free",
TEAM: "team", TEAM: "team",
PRO: "pro",
BUSINESS: "business", BUSINESS: "business",
ENTERPRISE: "enterprise", ENTERPRISE: "enterprise",
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/sdk", "name": "@budibase/sdk",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"description": "Budibase Public API SDK", "description": "Budibase Public API SDK",
"author": "Budibase", "author": "Budibase",
"license": "MPL-2.0", "license": "MPL-2.0",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/server", "name": "@budibase/server",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"description": "Budibase Web Server", "description": "Budibase Web Server",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -77,11 +77,11 @@
"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.0.14-alpha.0", "@budibase/backend-core": "2.0.14-alpha.4",
"@budibase/client": "2.0.14-alpha.0", "@budibase/client": "2.0.14-alpha.4",
"@budibase/pro": "2.0.14-alpha.0", "@budibase/pro": "2.0.14-alpha.4",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@budibase/types": "2.0.14-alpha.0", "@budibase/types": "2.0.14-alpha.4",
"@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",

View File

@ -66,9 +66,9 @@ exports.run = async function ({ inputs, appId, emitter }) {
} }
const tableId = inputs.row.tableId const tableId = inputs.row.tableId
// clear any falsy properties so that they aren't updated // clear any undefined, null or empty string properties so that they aren't updated
for (let propKey of Object.keys(inputs.row)) { for (let propKey of Object.keys(inputs.row)) {
if (!inputs.row[propKey] || inputs.row[propKey] === "") { if (inputs.row[propKey] == null || inputs.row[propKey] === "") {
delete inputs.row[propKey] delete inputs.row[propKey]
} }
} }

View File

@ -1094,12 +1094,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.0.14-alpha.0": "@budibase/backend-core@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.0.14-alpha.0.tgz#e4115967c9e37147216376bbabd622a9a13403d4" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.0.14-alpha.4.tgz#213446a9e04385fb38ab8785742cdb8b4eaf2cac"
integrity sha512-igWtifz/AFZx3kbQi7yO+dRDQX7mbY/ZCA2aRhmDIlhm3zky94XgFyG/7iPFmxh9jK+gpg1Sg3axY7vNDSX6+Q== integrity sha512-ma1Ipst4AQVi4sx+ULs3bX9xT4eHqavCvM/BXtZzV23SOTdjJTi9wX2KWbIvAUT5xo2NgN0uRf5zf7B6CBRuXw==
dependencies: dependencies:
"@budibase/types" "2.0.14-alpha.0" "@budibase/types" "2.0.14-alpha.4"
"@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-sdk "2.1030.0" aws-sdk "2.1030.0"
@ -1180,13 +1180,13 @@
svelte-flatpickr "^3.2.3" svelte-flatpickr "^3.2.3"
svelte-portal "^1.0.0" svelte-portal "^1.0.0"
"@budibase/pro@2.0.14-alpha.0": "@budibase/pro@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.0.14-alpha.0.tgz#e6cb571a0a757871e9ab65555470e2c9f4fc4403" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.0.14-alpha.4.tgz#9796271365f4ffb875655f86df84a2b4111b793a"
integrity sha512-Qh0U89AfnIpBA9fE4xH8hXYp4HexYSoc6WDjlVuNI46IvGRlHaeBAsRkI8XYG8mx830fQqVeEIY1WuRUso7bOg== integrity sha512-I5QIv04hfoUPEYHPkCD5L/5WU7cJurmfhjy62ZMTNbJzFzhIGDzQlOjM0MnQO5kJvGv1NWl2PQvSty1rYzXGsw==
dependencies: dependencies:
"@budibase/backend-core" "2.0.14-alpha.0" "@budibase/backend-core" "2.0.14-alpha.4"
"@budibase/types" "2.0.14-alpha.0" "@budibase/types" "2.0.14-alpha.4"
"@koa/router" "8.0.8" "@koa/router" "8.0.8"
joi "17.6.0" joi "17.6.0"
node-fetch "^2.6.1" node-fetch "^2.6.1"
@ -1209,10 +1209,10 @@
svelte-apexcharts "^1.0.2" svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0" svelte-flatpickr "^3.1.0"
"@budibase/types@2.0.14-alpha.0": "@budibase/types@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.0.14-alpha.0.tgz#419ceefde9698b1918c1b41f90fc3010927acde7" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.0.14-alpha.4.tgz#37b1ff362d2551fd978e8c8153a4cec357eda0b0"
integrity sha512-20+VfYR9oIui3PDExL+3Ld0XWkrbD74CfWHS8+dYiRmW/PqUkhAT0suwpNui5OsVUn1I+9Jw0wvbitpgT5u2VQ== integrity sha512-l4dfMh5it1N56nc+jCtdXklrZA1cMt6WSVBoKCXBedZGpguJr18Wo/cfn1YWryuUMuSlpFVDTrlQQXCZ+ku92g==
"@bull-board/api@3.7.0": "@bull-board/api@3.7.0":
version "3.7.0" version "3.7.0"

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/string-templates", "name": "@budibase/string-templates",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"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",

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/types", "name": "@budibase/types",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"description": "Budibase types", "description": "Budibase types",
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "2.0.14-alpha.0", "version": "2.0.14-alpha.4",
"description": "Budibase background service", "description": "Budibase background service",
"main": "src/index.ts", "main": "src/index.ts",
"repository": { "repository": {
@ -36,10 +36,10 @@
"author": "Budibase", "author": "Budibase",
"license": "GPL-3.0", "license": "GPL-3.0",
"dependencies": { "dependencies": {
"@budibase/backend-core": "2.0.14-alpha.0", "@budibase/backend-core": "2.0.14-alpha.4",
"@budibase/pro": "2.0.14-alpha.0", "@budibase/pro": "2.0.14-alpha.4",
"@budibase/string-templates": "2.0.14-alpha.0", "@budibase/string-templates": "2.0.14-alpha.4",
"@budibase/types": "2.0.14-alpha.0", "@budibase/types": "2.0.14-alpha.4",
"@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",

View File

@ -291,12 +291,12 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/backend-core@2.0.14-alpha.0": "@budibase/backend-core@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.0.14-alpha.0.tgz#e4115967c9e37147216376bbabd622a9a13403d4" resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-2.0.14-alpha.4.tgz#213446a9e04385fb38ab8785742cdb8b4eaf2cac"
integrity sha512-igWtifz/AFZx3kbQi7yO+dRDQX7mbY/ZCA2aRhmDIlhm3zky94XgFyG/7iPFmxh9jK+gpg1Sg3axY7vNDSX6+Q== integrity sha512-ma1Ipst4AQVi4sx+ULs3bX9xT4eHqavCvM/BXtZzV23SOTdjJTi9wX2KWbIvAUT5xo2NgN0uRf5zf7B6CBRuXw==
dependencies: dependencies:
"@budibase/types" "2.0.14-alpha.0" "@budibase/types" "2.0.14-alpha.4"
"@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-sdk "2.1030.0" aws-sdk "2.1030.0"
@ -327,21 +327,21 @@
uuid "8.3.2" uuid "8.3.2"
zlib "1.0.5" zlib "1.0.5"
"@budibase/pro@2.0.14-alpha.0": "@budibase/pro@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.0.14-alpha.0.tgz#e6cb571a0a757871e9ab65555470e2c9f4fc4403" resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-2.0.14-alpha.4.tgz#9796271365f4ffb875655f86df84a2b4111b793a"
integrity sha512-Qh0U89AfnIpBA9fE4xH8hXYp4HexYSoc6WDjlVuNI46IvGRlHaeBAsRkI8XYG8mx830fQqVeEIY1WuRUso7bOg== integrity sha512-I5QIv04hfoUPEYHPkCD5L/5WU7cJurmfhjy62ZMTNbJzFzhIGDzQlOjM0MnQO5kJvGv1NWl2PQvSty1rYzXGsw==
dependencies: dependencies:
"@budibase/backend-core" "2.0.14-alpha.0" "@budibase/backend-core" "2.0.14-alpha.4"
"@budibase/types" "2.0.14-alpha.0" "@budibase/types" "2.0.14-alpha.4"
"@koa/router" "8.0.8" "@koa/router" "8.0.8"
joi "17.6.0" joi "17.6.0"
node-fetch "^2.6.1" node-fetch "^2.6.1"
"@budibase/types@2.0.14-alpha.0": "@budibase/types@2.0.14-alpha.4":
version "2.0.14-alpha.0" version "2.0.14-alpha.4"
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.0.14-alpha.0.tgz#419ceefde9698b1918c1b41f90fc3010927acde7" resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.0.14-alpha.4.tgz#37b1ff362d2551fd978e8c8153a4cec357eda0b0"
integrity sha512-20+VfYR9oIui3PDExL+3Ld0XWkrbD74CfWHS8+dYiRmW/PqUkhAT0suwpNui5OsVUn1I+9Jw0wvbitpgT5u2VQ== integrity sha512-l4dfMh5it1N56nc+jCtdXklrZA1cMt6WSVBoKCXBedZGpguJr18Wo/cfn1YWryuUMuSlpFVDTrlQQXCZ+ku92g==
"@cspotcode/source-map-consumer@0.8.0": "@cspotcode/source-map-consumer@0.8.0":
version "0.8.0" version "0.8.0"

22
qa-core/README.md Normal file
View File

@ -0,0 +1,22 @@
# QA Core API Tests
The QA Core API tests are a jest suite that run directly against the budibase backend APIs.
## Auto Setup
You can run the whole test suite with one command, that spins up the budibase server and runs the jest tests:
`yarn api:test`
## Setup Server Only
You can also just stand up the budibase server alone.
`yarn api:server:setup`
## Run Tests
If you configured the server using the previous command, you can run the whole test suite by using:
`yarn test`
for watch mode, where the tests will run on every change:
`yarn test:watch`

View File

@ -25,7 +25,8 @@
"moduleNameMapper": { "moduleNameMapper": {
"@budibase/types": "<rootDir>/../packages/types/src", "@budibase/types": "<rootDir>/../packages/types/src",
"@budibase/server": "<rootDir>/../packages/server/src", "@budibase/server": "<rootDir>/../packages/server/src",
"@budibase/backend-core": "<rootDir>/../packages/backend-core/src" "@budibase/backend-core": "<rootDir>/../packages/backend-core/src",
"@budibase/backend-core/(.*)": "<rootDir>/../packages/backend-core/$1"
}, },
"setupFiles": [ "setupFiles": [
"./scripts/jestSetup.js" "./scripts/jestSetup.js"
@ -51,6 +52,7 @@
}, },
"dependencies": { "dependencies": {
"@budibase/backend-core": "^2.0.5", "@budibase/backend-core": "^2.0.5",
"form-data": "^4.0.0",
"node-fetch": "2" "node-fetch": "2"
} }
} }

View File

@ -15,3 +15,5 @@ tk.freeze(MOCK_DATE)
if (!process.env.DEBUG) { if (!process.env.DEBUG) {
global.console.log = jest.fn() // console.log are ignored in tests global.console.log = jest.fn() // console.log are ignored in tests
} }
jest.setTimeout(10000)

View File

@ -16,9 +16,7 @@ class InternalAPIClient {
constructor(appId?: string) { constructor(appId?: string) {
if (!env.BUDIBASE_SERVER_URL) { if (!env.BUDIBASE_SERVER_URL) {
throw new Error( throw new Error("Must set BUDIBASE_SERVER_URL env var")
"Must set BUDIBASE_SERVER_URL env var"
)
} }
this.host = `${env.BUDIBASE_SERVER_URL}/api` this.host = `${env.BUDIBASE_SERVER_URL}/api`
this.appId = appId this.appId = appId

View File

@ -1,8 +1,8 @@
import { import { Application } from "@budibase/server/api/controllers/public/mapping/types"
Application, import { App } from "@budibase/types"
} from "@budibase/server/api/controllers/public/mapping/types"
import { Response } from "node-fetch" import { Response } from "node-fetch"
import InternalAPIClient from "./InternalAPIClient" import InternalAPIClient from "./InternalAPIClient"
import FormData from "form-data"
export default class AppApi { export default class AppApi {
api: InternalAPIClient api: InternalAPIClient
@ -17,9 +17,25 @@ export default class AppApi {
return [response, json] return [response, json]
} }
async create( async canRender(): Promise<[Response, boolean]> {
body: any const response = await this.api.get("/routing/client")
): Promise<[Response, Application]> { const json = await response.json()
return [response, Object.keys(json.routes).length > 0]
}
async getAppPackage(appId: string): Promise<[Response, any]> {
const response = await this.api.get(`/applications/${appId}/appPackage`)
const json = await response.json()
return [response, json]
}
async publish(): Promise<[Response, string]> {
const response = await this.api.post("/deploy")
const json = await response.json()
return [response, json]
}
async create(body: any): Promise<[Response, Partial<App>]> {
const response = await this.api.post(`/applications`, { body }) const response = await this.api.post(`/applications`, { body })
const json = await response.json() const json = await response.json()
return [response, json] return [response, json]

View File

@ -12,8 +12,8 @@ export default class AuthApi {
const response = await this.api.post(`/global/auth/default/login`, { const response = await this.api.post(`/global/auth/default/login`, {
body: { body: {
username: process.env.BB_ADMIN_USER_EMAIL, username: process.env.BB_ADMIN_USER_EMAIL,
password: process.env.BB_ADMIN_USER_PASSWORD password: process.env.BB_ADMIN_USER_PASSWORD,
} },
}) })
const cookie = response.headers.get("set-cookie") const cookie = response.headers.get("set-cookie")
this.api.cookie = cookie as any this.api.cookie = cookie as any

View File

@ -13,9 +13,12 @@ export default class TestConfiguration<T> {
this.context = <T>{} this.context = <T>{}
} }
async beforeAll() {} async beforeAll() {
await this.auth.login()
}
async afterAll() { async afterAll() {
this.context = <T>{} this.context = <T>{}
await this.auth.logout()
} }
} }

View File

@ -1,10 +1,9 @@
import generator from "../../generator" import generator from "../../generator"
import { import { Application } from "@budibase/server/api/controllers/public/mapping/types"
Application,
} from "@budibase/server/api/controllers/public/mapping/types"
const generate = (
const generate = (overrides: Partial<Application> = {}): Partial<Application> => ({ overrides: Partial<Application> = {}
): Partial<Application> => ({
name: generator.word(), name: generator.word(),
url: `/${generator.word()}`, url: `/${generator.word()}`,
...overrides, ...overrides,

View File

@ -1,7 +1,9 @@
import TestConfiguration from "../../../config/internal-api/TestConfiguration" import TestConfiguration from "../../../config/internal-api/TestConfiguration"
import { Application } from "@budibase/server/api/controllers/public/mapping/types" import { Application } from "@budibase/server/api/controllers/public/mapping/types"
import { db } from "@budibase/backend-core"
import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient" import InternalAPIClient from "../../../config/internal-api/TestConfiguration/InternalAPIClient"
import generateApp from "../../../config/internal-api/fixtures/applications" import generateApp from "../../../config/internal-api/fixtures/applications"
import generator from "../../../config/generator"
describe("Internal API - /applications endpoints", () => { describe("Internal API - /applications endpoints", () => {
const api = new InternalAPIClient() const api = new InternalAPIClient()
@ -9,27 +11,31 @@ describe("Internal API - /applications endpoints", () => {
beforeAll(async () => { beforeAll(async () => {
await config.beforeAll() await config.beforeAll()
await config.auth.login()
}) })
afterAll(async () => { afterAll(async () => {
await config.afterAll() await config.afterAll()
await config.auth.logout()
}) })
it("POST - Can login", async () => { async function createAppFromTemplate() {
const [response] = await config.auth.login() return config.applications.create({
expect(response).toHaveStatusCode(200) name: generator.word(),
url: `/${generator.word()}`,
useTemplate: "true",
templateName: "Near Miss Register",
templateKey: "app/near-miss-register",
templateFile: undefined,
}) })
}
it("GET - fetch applications", async () => { it("GET - fetch applications", async () => {
await config.applications.create({ await config.applications.create({
...generateApp(), ...generateApp(),
useTemplate: false useTemplate: false,
}) })
const [response, apps] = await config.applications.fetch() const [response, apps] = await config.applications.fetch()
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(apps.length).toBeGreaterThan(1) expect(apps.length).toBeGreaterThanOrEqual(1)
}) })
it("POST - Create an application", async () => { it("POST - Create an application", async () => {
@ -37,4 +43,45 @@ describe("Internal API - /applications endpoints", () => {
expect(response).toHaveStatusCode(200) expect(response).toHaveStatusCode(200)
expect(app._id).toBeDefined() expect(app._id).toBeDefined()
}) })
it("POST - Publish application", async () => {
// create app
const [response, app] = await config.applications.create(generateApp())
expect(response).toHaveStatusCode(200)
expect(app.appId).toBeDefined()
// publish app
config.applications.api.appId = app.appId
const [publishResponse, publish] = await config.applications.publish()
expect(publishResponse).toHaveStatusCode(200)
expect(publish).toEqual({
_id: expect.any(String),
appUrl: app.url,
status: "SUCCESS",
})
})
it("POST - Create an application from a template, publish and check it renders", async () => {
// create the app
const appName = generator.word()
const [response, app] = await createAppFromTemplate()
expect(response).toHaveStatusCode(200)
expect(app.appId).toBeDefined()
config.applications.api.appId = app.appId
// check preview renders
const [previewResponse, previewRenders] =
await config.applications.canRender()
expect(previewResponse).toHaveStatusCode(200)
expect(previewRenders).toBe(true)
// publish app
await config.applications.publish()
// check published app renders
config.applications.api.appId = db.getProdAppID(app.appId)
const [publishedAppResponse, publishedAppRenders] =
await config.applications.canRender()
expect(publishedAppRenders).toBe(true)
})
}) })

View File

@ -14,7 +14,8 @@
"skipLibCheck": true, "skipLibCheck": true,
"paths": { "paths": {
"@budibase/types": ["../packages/types/src"], "@budibase/types": ["../packages/types/src"],
"@budibase/backend-core": ["../packages/backend-core"], "@budibase/backend-core": ["../packages/backend-core/src"],
"@budibase/backend-core/*": ["../packages/backend-core/*"],
"@budibase/server/*": ["../packages/server/src/*"], "@budibase/server/*": ["../packages/server/src/*"],
} }
}, },
@ -23,6 +24,7 @@
}, },
"references": [ "references": [
{ "path": "../packages/types" }, { "path": "../packages/types" },
{ "path": "../packages/backend-core" },
], ],
"include": [ "include": [
"src/**/*", "src/**/*",

View File

@ -1839,6 +1839,15 @@ form-data@^3.0.0:
combined-stream "^1.0.8" combined-stream "^1.0.8"
mime-types "^2.1.12" mime-types "^2.1.12"
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
form-data@~2.3.2: form-data@~2.3.2:
version "2.3.3" version "2.3.3"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6"