Merge branch 'master' of github.com:Budibase/budibase into develop
This commit is contained in:
commit
fd74cb3960
|
@ -19,8 +19,8 @@ ADD packages/worker .
|
||||||
RUN node /pinVersions.js && yarn && yarn build && /cleanup.sh
|
RUN node /pinVersions.js && yarn && yarn build && /cleanup.sh
|
||||||
|
|
||||||
FROM couchdb:3.2.1
|
FROM couchdb:3.2.1
|
||||||
# TARGETARCH can be amd64 or arm e.g. docker build --build-arg TARGETARCH=amd64
|
ARG TARGETARCH
|
||||||
ARG TARGETARCH=amd64
|
ENV TARGETARCH $TARGETARCH
|
||||||
#TARGETBUILD can be set to single (for single docker image) or aas (for azure app service)
|
#TARGETBUILD can be set to single (for single docker image) or aas (for azure app service)
|
||||||
# e.g. docker build --build-arg TARGETBUILD=aas ....
|
# e.g. docker build --build-arg TARGETBUILD=aas ....
|
||||||
ARG TARGETBUILD=single
|
ARG TARGETBUILD=single
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/types": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -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.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/bbui": "^2.0.23",
|
||||||
"@budibase/client": "2.0.14-alpha.1",
|
"@budibase/client": "^2.0.23",
|
||||||
"@budibase/frontend-core": "2.0.14-alpha.1",
|
"@budibase/frontend-core": "^2.0.23",
|
||||||
"@budibase/string-templates": "2.0.14-alpha.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -396,7 +396,6 @@ export const getUserBindings = () => {
|
||||||
|
|
||||||
bindings = keys.reduce((acc, key) => {
|
bindings = keys.reduce((acc, key) => {
|
||||||
const fieldSchema = schema[key]
|
const fieldSchema = schema[key]
|
||||||
if (fieldSchema.type !== "link") {
|
|
||||||
acc.push({
|
acc.push({
|
||||||
type: "context",
|
type: "context",
|
||||||
runtimeBinding: `${safeUser}.${makePropSafe(key)}`,
|
runtimeBinding: `${safeUser}.${makePropSafe(key)}`,
|
||||||
|
@ -408,7 +407,6 @@ export const getUserBindings = () => {
|
||||||
category: "Current User",
|
category: "Current User",
|
||||||
icon: "User",
|
icon: "User",
|
||||||
})
|
})
|
||||||
}
|
|
||||||
return acc
|
return acc
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/backend-core": "^2.0.23",
|
||||||
"@budibase/string-templates": "2.0.14-alpha.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@budibase/types": "2.0.14-alpha.1",
|
"@budibase/types": "^2.0.23",
|
||||||
"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,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/bbui": "^2.0.23",
|
||||||
"@budibase/frontend-core": "2.0.14-alpha.1",
|
"@budibase/frontend-core": "^2.0.23",
|
||||||
"@budibase/string-templates": "2.0.14-alpha.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
themeStore,
|
themeStore,
|
||||||
appStore,
|
appStore,
|
||||||
devToolsStore,
|
devToolsStore,
|
||||||
environmentStore,
|
|
||||||
} from "stores"
|
} from "stores"
|
||||||
import NotificationDisplay from "components/overlay/NotificationDisplay.svelte"
|
import NotificationDisplay from "components/overlay/NotificationDisplay.svelte"
|
||||||
import ConfirmationDisplay from "components/overlay/ConfirmationDisplay.svelte"
|
import ConfirmationDisplay from "components/overlay/ConfirmationDisplay.svelte"
|
||||||
|
@ -48,8 +47,6 @@
|
||||||
!$builderStore.inBuilder &&
|
!$builderStore.inBuilder &&
|
||||||
$devToolsStore.enabled &&
|
$devToolsStore.enabled &&
|
||||||
!$routeStore.queryParams?.peek
|
!$routeStore.queryParams?.peek
|
||||||
$: objectStoreUrl = $environmentStore.cloud ? "https://cdn.budi.live" : ""
|
|
||||||
$: pluginsUrl = `${objectStoreUrl}/plugins`
|
|
||||||
|
|
||||||
// Handle no matching route
|
// Handle no matching route
|
||||||
$: {
|
$: {
|
||||||
|
@ -95,8 +92,7 @@
|
||||||
<svelte:head>
|
<svelte:head>
|
||||||
{#if $builderStore.usedPlugins?.length}
|
{#if $builderStore.usedPlugins?.length}
|
||||||
{#each $builderStore.usedPlugins as plugin (plugin.hash)}
|
{#each $builderStore.usedPlugins as plugin (plugin.hash)}
|
||||||
<script
|
<script src={`${plugin.jsUrl}?r=${plugin.hash || ""}`}></script>
|
||||||
src={`${pluginsUrl}/${plugin.jsUrl}?r=${plugin.hash || ""}`}></script>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
</svelte:head>
|
</svelte:head>
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
export class ApexOptionsBuilder {
|
export class ApexOptionsBuilder {
|
||||||
formatters = {
|
constructor() {
|
||||||
|
this.formatters = {
|
||||||
["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100),
|
["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100),
|
||||||
["Thousands"]: val => `${Math.round(val / 1000)}K`,
|
["Thousands"]: val => `${Math.round(val / 1000)}K`,
|
||||||
["Millions"]: val => `${Math.round(val / 1000000)}M`,
|
["Millions"]: val => `${Math.round(val / 1000000)}M`,
|
||||||
}
|
}
|
||||||
options = {
|
this.options = {
|
||||||
series: [],
|
series: [],
|
||||||
legend: {
|
legend: {
|
||||||
show: false,
|
show: false,
|
||||||
|
@ -33,6 +34,7 @@ export class ApexOptionsBuilder {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
setOption(path, value) {
|
setOption(path, value) {
|
||||||
if (value == null || value === "") {
|
if (value == null || value === "") {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/bbui": "^2.0.23",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,23 @@ import { convertJSONSchemaToTableSchema } from "../utils/json"
|
||||||
* For other types of datasource, this class is overridden and extended.
|
* For other types of datasource, this class is overridden and extended.
|
||||||
*/
|
*/
|
||||||
export default class DataFetch {
|
export default class DataFetch {
|
||||||
|
/**
|
||||||
|
* Constructs a new DataFetch instance.
|
||||||
|
* @param opts the fetch options
|
||||||
|
*/
|
||||||
|
constructor(opts) {
|
||||||
// API client
|
// API client
|
||||||
API = null
|
this.API = null
|
||||||
|
|
||||||
// Feature flags
|
// Feature flags
|
||||||
featureStore = writable({
|
this.featureStore = writable({
|
||||||
supportsSearch: false,
|
supportsSearch: false,
|
||||||
supportsSort: false,
|
supportsSort: false,
|
||||||
supportsPagination: false,
|
supportsPagination: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
// Config
|
// Config
|
||||||
options = {
|
this.options = {
|
||||||
datasource: null,
|
datasource: null,
|
||||||
limit: 10,
|
limit: 10,
|
||||||
|
|
||||||
|
@ -43,7 +48,7 @@ export default class DataFetch {
|
||||||
}
|
}
|
||||||
|
|
||||||
// State of the fetch
|
// State of the fetch
|
||||||
store = writable({
|
this.store = writable({
|
||||||
rows: [],
|
rows: [],
|
||||||
info: null,
|
info: null,
|
||||||
schema: null,
|
schema: null,
|
||||||
|
@ -55,11 +60,6 @@ export default class DataFetch {
|
||||||
cursors: [],
|
cursors: [],
|
||||||
})
|
})
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructs a new DataFetch instance.
|
|
||||||
* @param opts the fetch options
|
|
||||||
*/
|
|
||||||
constructor(opts) {
|
|
||||||
// Merge options with their default values
|
// Merge options with their default values
|
||||||
this.API = opts?.API
|
this.API = opts?.API
|
||||||
this.options = {
|
this.options = {
|
||||||
|
|
|
@ -121,7 +121,12 @@ export const buildLuceneQuery = filter => {
|
||||||
query.allOr = true
|
query.allOr = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if (type === "datetime" && !isHbs) {
|
if (
|
||||||
|
type === "datetime" &&
|
||||||
|
!isHbs &&
|
||||||
|
operator !== "empty" &&
|
||||||
|
operator !== "notEmpty"
|
||||||
|
) {
|
||||||
// Ensure date value is a valid date and parse into correct format
|
// Ensure date value is a valid date and parse into correct format
|
||||||
if (!value) {
|
if (!value) {
|
||||||
return
|
return
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/sdk",
|
"name": "@budibase/sdk",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/backend-core": "^2.0.23",
|
||||||
"@budibase/client": "2.0.14-alpha.1",
|
"@budibase/client": "^2.0.23",
|
||||||
"@budibase/pro": "2.0.14-alpha.0",
|
"@budibase/pro": "2.0.23",
|
||||||
"@budibase/string-templates": "2.0.14-alpha.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@budibase/types": "2.0.14-alpha.1",
|
"@budibase/types": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -50,6 +50,7 @@ import { errors, events, migrations } from "@budibase/backend-core"
|
||||||
import { App, Layout, Screen, MigrationType } from "@budibase/types"
|
import { App, Layout, Screen, MigrationType } from "@budibase/types"
|
||||||
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts"
|
||||||
import { groups } from "@budibase/pro"
|
import { groups } from "@budibase/pro"
|
||||||
|
import { enrichPluginURLs } from "../../utilities/plugins"
|
||||||
|
|
||||||
const URL_REGEX_SLASH = /\/|\\/g
|
const URL_REGEX_SLASH = /\/|\\/g
|
||||||
|
|
||||||
|
@ -208,10 +209,13 @@ export const fetchAppDefinition = async (ctx: any) => {
|
||||||
|
|
||||||
export const fetchAppPackage = async (ctx: any) => {
|
export const fetchAppPackage = async (ctx: any) => {
|
||||||
const db = context.getAppDB()
|
const db = context.getAppDB()
|
||||||
const application = await db.get(DocumentType.APP_METADATA)
|
let application = await db.get(DocumentType.APP_METADATA)
|
||||||
const layouts = await getLayouts()
|
const layouts = await getLayouts()
|
||||||
let screens = await getScreens()
|
let screens = await getScreens()
|
||||||
|
|
||||||
|
// Enrich plugin URLs
|
||||||
|
application.usedPlugins = enrichPluginURLs(application.usedPlugins)
|
||||||
|
|
||||||
// Only filter screens if the user is not a builder
|
// Only filter screens if the user is not a builder
|
||||||
if (!(ctx.user.builder && ctx.user.builder.global)) {
|
if (!(ctx.user.builder && ctx.user.builder.global)) {
|
||||||
const userRoleId = getUserRoleId(ctx)
|
const userRoleId = getUserRoleId(ctx)
|
||||||
|
|
|
@ -68,6 +68,7 @@ exports.buildSchemaFromDb = async function (ctx) {
|
||||||
datasource.entities = tables
|
datasource.entities = tables
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setDefaultDisplayColumns(datasource)
|
||||||
const dbResp = await db.put(datasource)
|
const dbResp = await db.put(datasource)
|
||||||
datasource._rev = dbResp.rev
|
datasource._rev = dbResp.rev
|
||||||
|
|
||||||
|
@ -78,6 +79,24 @@ exports.buildSchemaFromDb = async function (ctx) {
|
||||||
ctx.body = response
|
ctx.body = response
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Make sure all datasource entities have a display name selected
|
||||||
|
*/
|
||||||
|
const setDefaultDisplayColumns = datasource => {
|
||||||
|
//
|
||||||
|
for (let entity of Object.values(datasource.entities)) {
|
||||||
|
if (entity.primaryDisplay) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
const notAutoColumn = Object.values(entity.schema).find(
|
||||||
|
schema => !schema.autocolumn
|
||||||
|
)
|
||||||
|
if (notAutoColumn) {
|
||||||
|
entity.primaryDisplay = notAutoColumn.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check for variables that have been updated or removed and invalidate them.
|
* Check for variables that have been updated or removed and invalidate them.
|
||||||
*/
|
*/
|
||||||
|
@ -155,6 +174,7 @@ exports.save = async function (ctx) {
|
||||||
const { tables, error } = await buildSchemaHelper(datasource)
|
const { tables, error } = await buildSchemaHelper(datasource)
|
||||||
schemaError = error
|
schemaError = error
|
||||||
datasource.entities = tables
|
datasource.entities = tables
|
||||||
|
setDefaultDisplayColumns(datasource)
|
||||||
}
|
}
|
||||||
|
|
||||||
const dbResp = await db.put(datasource)
|
const dbResp = await db.put(datasource)
|
||||||
|
@ -238,19 +258,6 @@ const buildSchemaHelper = async datasource => {
|
||||||
const connector = new Connector(datasource.config)
|
const connector = new Connector(datasource.config)
|
||||||
await connector.buildSchema(datasource._id, datasource.entities)
|
await connector.buildSchema(datasource._id, datasource.entities)
|
||||||
|
|
||||||
// make sure they all have a display name selected
|
|
||||||
for (let entity of Object.values(datasource.entities ?? {})) {
|
|
||||||
if (entity.primaryDisplay) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
const notAutoColumn = Object.values(entity.schema).find(
|
|
||||||
schema => !schema.autocolumn
|
|
||||||
)
|
|
||||||
if (notAutoColumn) {
|
|
||||||
entity.primaryDisplay = notAutoColumn.name
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const errors = connector.schemaErrors
|
const errors = connector.schemaErrors
|
||||||
let error = null
|
let error = null
|
||||||
if (errors && Object.keys(errors).length > 0) {
|
if (errors && Object.keys(errors).length > 0) {
|
||||||
|
|
|
@ -52,14 +52,19 @@ export async function read(ctx: any, next: any) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function update(ctx: any, next: any) {
|
export async function update(ctx: any, next: any) {
|
||||||
ctx.request.body = await addRev(fixRow(ctx.request.body, ctx.params))
|
const { tableId } = ctx.params
|
||||||
|
ctx.request.body = await addRev(fixRow(ctx.request.body, ctx.params), tableId)
|
||||||
await rowController.save(ctx)
|
await rowController.save(ctx)
|
||||||
await next()
|
await next()
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function destroy(ctx: any, next: any) {
|
export async function destroy(ctx: any, next: any) {
|
||||||
|
const { tableId } = ctx.params
|
||||||
// set the body as expected, with the _id and _rev fields
|
// set the body as expected, with the _id and _rev fields
|
||||||
ctx.request.body = await addRev(fixRow({ _id: ctx.params.rowId }, ctx.params))
|
ctx.request.body = await addRev(
|
||||||
|
fixRow({ _id: ctx.params.rowId }, ctx.params),
|
||||||
|
tableId
|
||||||
|
)
|
||||||
await rowController.destroy(ctx)
|
await rowController.destroy(ctx)
|
||||||
// destroy controller doesn't currently return the row as the body, need to adjust this
|
// destroy controller doesn't currently return the row as the body, need to adjust this
|
||||||
// in the public API to be correct
|
// in the public API to be correct
|
||||||
|
|
|
@ -22,7 +22,7 @@ export async function addRev(
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Performs a case insensitive search on the provided documents, using the
|
* Performs a case in-sensitive search on the provided documents, using the
|
||||||
* provided key and value. This will be a string based search, using the
|
* provided key and value. This will be a string based search, using the
|
||||||
* startsWith function.
|
* startsWith function.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -240,6 +240,10 @@ async function execute(
|
||||||
const { rows, pagination, extra } = await quotas.addQuery(runFn, {
|
const { rows, pagination, extra } = await quotas.addQuery(runFn, {
|
||||||
datasourceId: datasource._id,
|
datasourceId: datasource._id,
|
||||||
})
|
})
|
||||||
|
// remove the raw from execution incase transformer being used to hide data
|
||||||
|
if (extra?.raw) {
|
||||||
|
delete extra.raw
|
||||||
|
}
|
||||||
if (opts && opts.rowsOnly) {
|
if (opts && opts.rowsOnly) {
|
||||||
ctx.body = rows
|
ctx.body = rows
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -145,7 +145,7 @@ class QueryBuilder {
|
||||||
* @param options The preprocess options
|
* @param options The preprocess options
|
||||||
* @returns {string|*}
|
* @returns {string|*}
|
||||||
*/
|
*/
|
||||||
preprocess(value, { escape, lowercase, wrap } = {}) {
|
preprocess(value, { escape, lowercase, wrap, type } = {}) {
|
||||||
const hasVersion = !!this.version
|
const hasVersion = !!this.version
|
||||||
// Determine if type needs wrapped
|
// Determine if type needs wrapped
|
||||||
const originalType = typeof value
|
const originalType = typeof value
|
||||||
|
@ -157,8 +157,11 @@ class QueryBuilder {
|
||||||
if (escape && originalType === "string") {
|
if (escape && originalType === "string") {
|
||||||
value = `${value}`.replace(/[ #+\-&|!(){}\]^"~*?:\\]/g, "\\$&")
|
value = `${value}`.replace(/[ #+\-&|!(){}\]^"~*?:\\]/g, "\\$&")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wrap in quotes
|
// Wrap in quotes
|
||||||
if (hasVersion && wrap) {
|
if (originalType === "string" && !isNaN(value) && !type) {
|
||||||
|
value = `"${value}"`
|
||||||
|
} else if (hasVersion && wrap) {
|
||||||
value = originalType === "number" ? value : `"${value}"`
|
value = originalType === "number" ? value : `"${value}"`
|
||||||
}
|
}
|
||||||
return value
|
return value
|
||||||
|
@ -253,6 +256,7 @@ class QueryBuilder {
|
||||||
value = builder.preprocess(value, {
|
value = builder.preprocess(value, {
|
||||||
escape: true,
|
escape: true,
|
||||||
lowercase: true,
|
lowercase: true,
|
||||||
|
type: "string",
|
||||||
})
|
})
|
||||||
return `${key}:${value}*`
|
return `${key}:${value}*`
|
||||||
})
|
})
|
||||||
|
@ -281,6 +285,7 @@ class QueryBuilder {
|
||||||
value = builder.preprocess(value, {
|
value = builder.preprocess(value, {
|
||||||
escape: true,
|
escape: true,
|
||||||
lowercase: true,
|
lowercase: true,
|
||||||
|
type: "fuzzy",
|
||||||
})
|
})
|
||||||
return `${key}:${value}~`
|
return `${key}:${value}~`
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { enrichPluginURLs } from "../../../utilities/plugins"
|
||||||
|
|
||||||
require("svelte/register")
|
require("svelte/register")
|
||||||
|
|
||||||
const send = require("koa-send")
|
const send = require("koa-send")
|
||||||
|
@ -107,12 +109,13 @@ export const serveApp = async function (ctx: any) {
|
||||||
|
|
||||||
if (!env.isJest()) {
|
if (!env.isJest()) {
|
||||||
const App = require("./templates/BudibaseApp.svelte").default
|
const App = require("./templates/BudibaseApp.svelte").default
|
||||||
|
const plugins = enrichPluginURLs(appInfo.usedPlugins)
|
||||||
const { head, html, css } = App.render({
|
const { head, html, css } = App.render({
|
||||||
title: appInfo.name,
|
title: appInfo.name,
|
||||||
production: env.isProd(),
|
production: env.isProd(),
|
||||||
appId,
|
appId,
|
||||||
clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
|
clientLibPath: clientLibraryPath(appId, appInfo.version, ctx),
|
||||||
usedPlugins: appInfo.usedPlugins,
|
usedPlugins: plugins,
|
||||||
})
|
})
|
||||||
|
|
||||||
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
|
const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`)
|
||||||
|
|
|
@ -88,9 +88,7 @@
|
||||||
<!-- But before loadBudibase is called -->
|
<!-- But before loadBudibase is called -->
|
||||||
{#if usedPlugins?.length}
|
{#if usedPlugins?.length}
|
||||||
{#each usedPlugins as plugin}
|
{#each usedPlugins as plugin}
|
||||||
<script
|
<script type="application/javascript" src={plugin.jsUrl}></script>
|
||||||
type="application/javascript"
|
|
||||||
src={`/plugins/${plugin.jsUrl}`}></script>
|
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
<script type="application/javascript">
|
<script type="application/javascript">
|
||||||
|
|
|
@ -14,8 +14,10 @@ import {
|
||||||
fixAutoColumnSubType,
|
fixAutoColumnSubType,
|
||||||
} from "../../../utilities/rowProcessor"
|
} from "../../../utilities/rowProcessor"
|
||||||
import { runStaticFormulaChecks } from "./bulkFormula"
|
import { runStaticFormulaChecks } from "./bulkFormula"
|
||||||
import { Table } from "../../../definitions/common"
|
import { Table } from "@budibase/types"
|
||||||
import { quotas } from "@budibase/pro"
|
import { quotas } from "@budibase/pro"
|
||||||
|
import { isEqual } from "lodash"
|
||||||
|
import { cloneDeep } from "lodash/fp"
|
||||||
|
|
||||||
function checkAutoColumns(table: Table, oldTable: Table) {
|
function checkAutoColumns(table: Table, oldTable: Table) {
|
||||||
if (!table.schema) {
|
if (!table.schema) {
|
||||||
|
@ -123,10 +125,16 @@ export async function save(ctx: any) {
|
||||||
if (updatedRows && updatedRows.length !== 0) {
|
if (updatedRows && updatedRows.length !== 0) {
|
||||||
await db.bulkDocs(updatedRows)
|
await db.bulkDocs(updatedRows)
|
||||||
}
|
}
|
||||||
const result = await db.put(tableToSave)
|
let result = await db.put(tableToSave)
|
||||||
tableToSave._rev = result.rev
|
tableToSave._rev = result.rev
|
||||||
|
const savedTable = cloneDeep(tableToSave)
|
||||||
|
|
||||||
tableToSave = await tableSaveFunctions.after(tableToSave)
|
tableToSave = await tableSaveFunctions.after(tableToSave)
|
||||||
|
// the table may be updated as part of the table save after functionality - need to write it
|
||||||
|
if (!isEqual(savedTable, tableToSave)) {
|
||||||
|
result = await db.put(tableToSave)
|
||||||
|
tableToSave._rev = result.rev
|
||||||
|
}
|
||||||
// has to run after, make sure it has _id
|
// has to run after, make sure it has _id
|
||||||
await runStaticFormulaChecks(tableToSave, { oldTable, deletion: null })
|
await runStaticFormulaChecks(tableToSave, { oldTable, deletion: null })
|
||||||
return tableToSave
|
return tableToSave
|
||||||
|
|
|
@ -247,7 +247,7 @@ class TableSaveFunctions {
|
||||||
// after saving
|
// after saving
|
||||||
async after(table: any) {
|
async after(table: any) {
|
||||||
table = await handleSearchIndexes(table)
|
table = await handleSearchIndexes(table)
|
||||||
await handleDataImport(this.user, table, this.dataImport)
|
table = await handleDataImport(this.user, table, this.dataImport)
|
||||||
return table
|
return table
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -173,4 +173,24 @@ describe("internal search", () => {
|
||||||
}, PARAMS)
|
}, PARAMS)
|
||||||
checkLucene(response, `*:* AND NOT column:(a AND b AND c)`, PARAMS)
|
checkLucene(response, `*:* AND NOT column:(a AND b AND c)`, PARAMS)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it("test equal without version query", async () => {
|
||||||
|
PARAMS.version = null
|
||||||
|
const response = await search.paginatedSearch({
|
||||||
|
equal: {
|
||||||
|
"column": "1",
|
||||||
|
}
|
||||||
|
}, PARAMS)
|
||||||
|
|
||||||
|
const query = response.rows[0].query
|
||||||
|
const json = JSON.parse(query)
|
||||||
|
if (PARAMS.sort) {
|
||||||
|
expect(json.sort).toBe(`${PARAMS.sort}<${PARAMS.sortType}>`)
|
||||||
|
}
|
||||||
|
if (PARAMS.bookmark) {
|
||||||
|
expect(json.bookmark).toBe(PARAMS.bookmark)
|
||||||
|
}
|
||||||
|
expect(json.include_docs).toBe(true)
|
||||||
|
expect(json.q).toBe(`(*:* AND column:"1") AND tableId:${PARAMS.tableId}`)
|
||||||
|
})
|
||||||
})
|
})
|
|
@ -252,7 +252,7 @@ class Orchestrator {
|
||||||
let loopStepNumber: any = undefined
|
let loopStepNumber: any = undefined
|
||||||
let loopSteps: LoopStep[] | undefined = []
|
let loopSteps: LoopStep[] | undefined = []
|
||||||
let metadata
|
let metadata
|
||||||
|
let wasLoopStep = false
|
||||||
// check if this is a recurring automation,
|
// check if this is a recurring automation,
|
||||||
if (isProdAppID(this._appId) && isRecurring(automation)) {
|
if (isProdAppID(this._appId) && isRecurring(automation)) {
|
||||||
metadata = await this.getMetadata()
|
metadata = await this.getMetadata()
|
||||||
|
@ -267,6 +267,7 @@ class Orchestrator {
|
||||||
let input,
|
let input,
|
||||||
iterations = 1,
|
iterations = 1,
|
||||||
iterationCount = 0
|
iterationCount = 0
|
||||||
|
|
||||||
if (step.stepId === LOOP_STEP_ID) {
|
if (step.stepId === LOOP_STEP_ID) {
|
||||||
loopStep = step
|
loopStep = step
|
||||||
loopStepNumber = stepCount
|
loopStepNumber = stepCount
|
||||||
|
@ -277,10 +278,8 @@ class Orchestrator {
|
||||||
input = await processObject(loopStep.inputs, this._context)
|
input = await processObject(loopStep.inputs, this._context)
|
||||||
iterations = getLoopIterations(loopStep as LoopStep, input)
|
iterations = getLoopIterations(loopStep as LoopStep, input)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let index = 0; index < iterations; index++) {
|
for (let index = 0; index < iterations; index++) {
|
||||||
let originalStepInput = cloneDeep(step.inputs)
|
let originalStepInput = cloneDeep(step.inputs)
|
||||||
|
|
||||||
// Handle if the user has set a max iteration count or if it reaches the max limit set by us
|
// Handle if the user has set a max iteration count or if it reaches the max limit set by us
|
||||||
if (loopStep && input.binding) {
|
if (loopStep && input.binding) {
|
||||||
let newInput = await processObject(
|
let newInput = await processObject(
|
||||||
|
@ -313,7 +312,6 @@ class Orchestrator {
|
||||||
} else {
|
} else {
|
||||||
item = loopStep.inputs.binding
|
item = loopStep.inputs.binding
|
||||||
}
|
}
|
||||||
|
|
||||||
this._context.steps[loopStepNumber] = {
|
this._context.steps[loopStepNumber] = {
|
||||||
currentItem: item[index],
|
currentItem: item[index],
|
||||||
}
|
}
|
||||||
|
@ -331,6 +329,16 @@ class Orchestrator {
|
||||||
innerValue,
|
innerValue,
|
||||||
`steps.${loopStepNumber}`
|
`steps.${loopStepNumber}`
|
||||||
)
|
)
|
||||||
|
} else if (typeof value === "object") {
|
||||||
|
for (let [innerObject, innerValue] of Object.entries(
|
||||||
|
originalStepInput[key][innerKey]
|
||||||
|
)) {
|
||||||
|
originalStepInput[key][innerKey][innerObject] =
|
||||||
|
automationUtils.substituteLoopStep(
|
||||||
|
innerValue,
|
||||||
|
`steps.${loopStepNumber}`
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -386,6 +394,7 @@ class Orchestrator {
|
||||||
let stepFn = await this.getStepFunctionality(step.stepId)
|
let stepFn = await this.getStepFunctionality(step.stepId)
|
||||||
let inputs = await processObject(originalStepInput, this._context)
|
let inputs = await processObject(originalStepInput, this._context)
|
||||||
inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
|
inputs = automationUtils.cleanInputValues(inputs, step.schema.inputs)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// appId is always passed
|
// appId is always passed
|
||||||
const outputs = await stepFn({
|
const outputs = await stepFn({
|
||||||
|
@ -394,6 +403,7 @@ class Orchestrator {
|
||||||
emitter: this._emitter,
|
emitter: this._emitter,
|
||||||
context: this._context,
|
context: this._context,
|
||||||
})
|
})
|
||||||
|
|
||||||
this._context.steps[stepCount] = outputs
|
this._context.steps[stepCount] = outputs
|
||||||
// if filter causes us to stop execution don't break the loop, set a var
|
// if filter causes us to stop execution don't break the loop, set a var
|
||||||
// so that we can finish iterating through the steps and record that it stopped
|
// so that we can finish iterating through the steps and record that it stopped
|
||||||
|
@ -419,6 +429,7 @@ class Orchestrator {
|
||||||
console.error(`Automation error - ${step.stepId} - ${err}`)
|
console.error(`Automation error - ${step.stepId} - ${err}`)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loopStep) {
|
if (loopStep) {
|
||||||
iterationCount++
|
iterationCount++
|
||||||
if (index === iterations - 1) {
|
if (index === iterations - 1) {
|
||||||
|
@ -429,6 +440,13 @@ class Orchestrator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Delete the step after the loop step as it's irrelevant, since information is included
|
||||||
|
// in the loop step
|
||||||
|
if (wasLoopStep) {
|
||||||
|
this._context.steps.splice(loopStepNumber + 1, 1)
|
||||||
|
wasLoopStep = false
|
||||||
|
}
|
||||||
|
|
||||||
if (loopSteps && loopSteps.length) {
|
if (loopSteps && loopSteps.length) {
|
||||||
let tempOutput = {
|
let tempOutput = {
|
||||||
success: true,
|
success: true,
|
||||||
|
@ -441,9 +459,10 @@ class Orchestrator {
|
||||||
outputs: tempOutput,
|
outputs: tempOutput,
|
||||||
inputs: step.inputs,
|
inputs: step.inputs,
|
||||||
})
|
})
|
||||||
|
this._context.steps[loopStepNumber] = tempOutput
|
||||||
|
|
||||||
this._context.steps.splice(loopStepNumber, 0, tempOutput)
|
|
||||||
loopSteps = undefined
|
loopSteps = undefined
|
||||||
|
wasLoopStep = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
const env = require("../environment")
|
||||||
|
const { plugins: ProPlugins } = require("@budibase/pro")
|
||||||
|
const { objectStore } = require("@budibase/backend-core")
|
||||||
|
|
||||||
|
exports.enrichPluginURLs = plugins => {
|
||||||
|
if (!plugins || !plugins.length) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
return plugins.map(plugin => {
|
||||||
|
const cloud = !env.SELF_HOSTED
|
||||||
|
const bucket = objectStore.ObjectStoreBuckets.PLUGINS
|
||||||
|
const jsFileName = "plugin.min.js"
|
||||||
|
|
||||||
|
// In self host we need to prefix the path, as the bucket name is not part
|
||||||
|
// of the bucket path. In cloud, it's already part of the bucket path.
|
||||||
|
let jsUrl = cloud ? "https://cdn.budi.live/" : `/${bucket}/`
|
||||||
|
jsUrl += ProPlugins.getBucketPath(plugin.name)
|
||||||
|
jsUrl += jsFileName
|
||||||
|
return { ...plugin, jsUrl }
|
||||||
|
})
|
||||||
|
}
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"description": "Budibase types",
|
"description": "Budibase types",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "2.0.14-alpha.1",
|
"version": "2.0.23",
|
||||||
"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.1",
|
"@budibase/backend-core": "^2.0.23",
|
||||||
"@budibase/pro": "2.0.14-alpha.0",
|
"@budibase/pro": "2.0.23",
|
||||||
"@budibase/string-templates": "2.0.14-alpha.1",
|
"@budibase/string-templates": "^2.0.23",
|
||||||
"@budibase/types": "2.0.14-alpha.1",
|
"@budibase/types": "^2.0.23",
|
||||||
"@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",
|
||||||
|
|
|
@ -1,8 +1,10 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
if [[ $TARGETARCH == arm* ]] ;
|
if [[ $TARGETARCH == arm* ]] ;
|
||||||
then
|
then
|
||||||
|
echo "INSTALLING ARM64 MINIO"
|
||||||
wget https://dl.min.io/server/minio/release/linux-arm64/minio
|
wget https://dl.min.io/server/minio/release/linux-arm64/minio
|
||||||
else
|
else
|
||||||
|
echo "INSTALLING AMD64 MINIO"
|
||||||
wget https://dl.min.io/server/minio/release/linux-amd64/minio
|
wget https://dl.min.io/server/minio/release/linux-amd64/minio
|
||||||
fi
|
fi
|
||||||
chmod +x minio
|
chmod +x minio
|
||||||
|
|
|
@ -18,6 +18,11 @@ git clone https://$PERSONAL_ACCESS_TOKEN@github.com/Budibase/budibase-pro.git
|
||||||
if [[ -d "budibase-pro" ]]; then
|
if [[ -d "budibase-pro" ]]; then
|
||||||
cd budibase-pro
|
cd budibase-pro
|
||||||
|
|
||||||
|
if [[ -z "${BRANCH}" ]]; then
|
||||||
|
echo Using GITHUB_REF_NAME: $GITHUB_REF_NAME
|
||||||
|
export BRANCH=$GITHUB_REF_NAME
|
||||||
|
fi
|
||||||
|
|
||||||
# Try to checkout the matching pro branch
|
# Try to checkout the matching pro branch
|
||||||
git checkout $BRANCH
|
git checkout $BRANCH
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue