diff --git a/hosting/single/Dockerfile b/hosting/single/Dockerfile index f34290f627..58796f0362 100644 --- a/hosting/single/Dockerfile +++ b/hosting/single/Dockerfile @@ -19,8 +19,8 @@ ADD packages/worker . RUN node /pinVersions.js && yarn && yarn build && /cleanup.sh FROM couchdb:3.2.1 -# TARGETARCH can be amd64 or arm e.g. docker build --build-arg TARGETARCH=amd64 -ARG TARGETARCH=amd64 +ARG TARGETARCH +ENV TARGETARCH $TARGETARCH #TARGETBUILD can be set to single (for single docker image) or aas (for azure app service) # e.g. docker build --build-arg TARGETBUILD=aas .... ARG TARGETBUILD=single diff --git a/lerna.json b/lerna.json index 69a8cb66a4..bc62b3c368 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.0.14-alpha.1", + "version": "2.0.23", "npmClient": "yarn", "packages": [ "packages/*" diff --git a/packages/backend-core/package.json b/packages/backend-core/package.json index 7ab82fcd60..a9c1e3eb59 100644 --- a/packages/backend-core/package.json +++ b/packages/backend-core/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/backend-core", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "description": "Budibase backend core libraries used in server and worker", "main": "dist/src/index.js", "types": "dist/src/index.d.ts", @@ -20,7 +20,7 @@ "test:watch": "jest --watchAll" }, "dependencies": { - "@budibase/types": "2.0.14-alpha.1", + "@budibase/types": "^2.0.23", "@shopify/jest-koa-mocks": "5.0.1", "@techpass/passport-openidconnect": "0.3.2", "aws-sdk": "2.1030.0", diff --git a/packages/bbui/package.json b/packages/bbui/package.json index d5557bc3c5..3ca5585e34 100644 --- a/packages/bbui/package.json +++ b/packages/bbui/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/bbui", "description": "A UI solution used in the different Budibase projects.", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "license": "MPL-2.0", "svelte": "src/index.js", "module": "dist/bbui.es.js", @@ -38,7 +38,7 @@ ], "dependencies": { "@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/actiongroup": "^1.0.1", "@spectrum-css/avatar": "^3.0.2", diff --git a/packages/builder/package.json b/packages/builder/package.json index 631b1988ad..6f289d3433 100644 --- a/packages/builder/package.json +++ b/packages/builder/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/builder", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "license": "GPL-3.0", "private": true, "scripts": { @@ -71,10 +71,10 @@ } }, "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", - "@budibase/client": "2.0.14-alpha.1", - "@budibase/frontend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", + "@budibase/bbui": "^2.0.23", + "@budibase/client": "^2.0.23", + "@budibase/frontend-core": "^2.0.23", + "@budibase/string-templates": "^2.0.23", "@sentry/browser": "5.19.1", "@spectrum-css/page": "^3.0.1", "@spectrum-css/vars": "^3.0.1", diff --git a/packages/builder/src/builderStore/dataBinding.js b/packages/builder/src/builderStore/dataBinding.js index 7456ec5691..c83daa7807 100644 --- a/packages/builder/src/builderStore/dataBinding.js +++ b/packages/builder/src/builderStore/dataBinding.js @@ -396,19 +396,17 @@ export const getUserBindings = () => { bindings = keys.reduce((acc, key) => { const fieldSchema = schema[key] - if (fieldSchema.type !== "link") { - acc.push({ - type: "context", - runtimeBinding: `${safeUser}.${makePropSafe(key)}`, - readableBinding: `Current User.${key}`, - // Field schema and provider are required to construct relationship - // datasource options, based on bindable properties - fieldSchema, - providerId: "user", - category: "Current User", - icon: "User", - }) - } + acc.push({ + type: "context", + runtimeBinding: `${safeUser}.${makePropSafe(key)}`, + readableBinding: `Current User.${key}`, + // Field schema and provider are required to construct relationship + // datasource options, based on bindable properties + fieldSchema, + providerId: "user", + category: "Current User", + icon: "User", + }) return acc }, []) diff --git a/packages/cli/package.json b/packages/cli/package.json index 6f094416f8..e054839f25 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/cli", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "description": "Budibase CLI, for developers, self hosting and migrations.", "main": "src/index.js", "bin": { @@ -26,9 +26,9 @@ "outputPath": "build" }, "dependencies": { - "@budibase/backend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", - "@budibase/types": "2.0.14-alpha.1", + "@budibase/backend-core": "^2.0.23", + "@budibase/string-templates": "^2.0.23", + "@budibase/types": "^2.0.23", "axios": "0.21.2", "chalk": "4.1.0", "cli-progress": "3.11.2", diff --git a/packages/client/package.json b/packages/client/package.json index 86ba8c5088..f22039ae4f 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/client", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "license": "MPL-2.0", "module": "dist/budibase-client.js", "main": "dist/budibase-client.js", @@ -19,9 +19,9 @@ "dev:builder": "rollup -cw" }, "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", - "@budibase/frontend-core": "2.0.14-alpha.1", - "@budibase/string-templates": "2.0.14-alpha.1", + "@budibase/bbui": "^2.0.23", + "@budibase/frontend-core": "^2.0.23", + "@budibase/string-templates": "^2.0.23", "@spectrum-css/button": "^3.0.3", "@spectrum-css/card": "^3.0.3", "@spectrum-css/divider": "^1.0.3", diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte index ab19e91038..537e963ff3 100644 --- a/packages/client/src/components/ClientApp.svelte +++ b/packages/client/src/components/ClientApp.svelte @@ -16,7 +16,6 @@ themeStore, appStore, devToolsStore, - environmentStore, } from "stores" import NotificationDisplay from "components/overlay/NotificationDisplay.svelte" import ConfirmationDisplay from "components/overlay/ConfirmationDisplay.svelte" @@ -48,8 +47,6 @@ !$builderStore.inBuilder && $devToolsStore.enabled && !$routeStore.queryParams?.peek - $: objectStoreUrl = $environmentStore.cloud ? "https://cdn.budi.live" : "" - $: pluginsUrl = `${objectStoreUrl}/plugins` // Handle no matching route $: { @@ -95,8 +92,7 @@ {#if $builderStore.usedPlugins?.length} {#each $builderStore.usedPlugins as plugin (plugin.hash)} - + {/each} {/if} diff --git a/packages/client/src/components/app/charts/ApexOptionsBuilder.js b/packages/client/src/components/app/charts/ApexOptionsBuilder.js index 31c5a820f7..6b3e3a4440 100644 --- a/packages/client/src/components/app/charts/ApexOptionsBuilder.js +++ b/packages/client/src/components/app/charts/ApexOptionsBuilder.js @@ -1,37 +1,39 @@ export class ApexOptionsBuilder { - formatters = { - ["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100), - ["Thousands"]: val => `${Math.round(val / 1000)}K`, - ["Millions"]: val => `${Math.round(val / 1000000)}M`, - } - options = { - series: [], - legend: { - show: false, - position: "top", - horizontalAlign: "right", - showForSingleSeries: true, - showForNullSeries: true, - showForZeroSeries: true, - }, - chart: { - toolbar: { + constructor() { + this.formatters = { + ["Default"]: val => (isNaN(val) ? val : Math.round(val * 100) / 100), + ["Thousands"]: val => `${Math.round(val / 1000)}K`, + ["Millions"]: val => `${Math.round(val / 1000000)}M`, + } + this.options = { + series: [], + legend: { show: false, + position: "top", + horizontalAlign: "right", + showForSingleSeries: true, + showForNullSeries: true, + showForZeroSeries: true, }, - zoom: { - enabled: false, + chart: { + toolbar: { + show: false, + }, + zoom: { + enabled: false, + }, }, - }, - xaxis: { - labels: { - formatter: this.formatters.Default, + xaxis: { + labels: { + formatter: this.formatters.Default, + }, }, - }, - yaxis: { - labels: { - formatter: this.formatters.Default, + yaxis: { + labels: { + formatter: this.formatters.Default, + }, }, - }, + } } setOption(path, value) { diff --git a/packages/frontend-core/package.json b/packages/frontend-core/package.json index b98282b9bd..3942ad481b 100644 --- a/packages/frontend-core/package.json +++ b/packages/frontend-core/package.json @@ -1,12 +1,12 @@ { "name": "@budibase/frontend-core", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "description": "Budibase frontend core libraries used in builder and client", "author": "Budibase", "license": "MPL-2.0", "svelte": "src/index.js", "dependencies": { - "@budibase/bbui": "2.0.14-alpha.1", + "@budibase/bbui": "^2.0.23", "lodash": "^4.17.21", "svelte": "^3.46.2" } diff --git a/packages/frontend-core/src/fetch/DataFetch.js b/packages/frontend-core/src/fetch/DataFetch.js index a3cc1c231c..31007121f1 100644 --- a/packages/frontend-core/src/fetch/DataFetch.js +++ b/packages/frontend-core/src/fetch/DataFetch.js @@ -14,52 +14,52 @@ import { convertJSONSchemaToTableSchema } from "../utils/json" * For other types of datasource, this class is overridden and extended. */ export default class DataFetch { - // API client - API = null - - // Feature flags - featureStore = writable({ - supportsSearch: false, - supportsSort: false, - supportsPagination: false, - }) - - // Config - options = { - datasource: null, - limit: 10, - - // Search config - filter: null, - query: null, - - // Sorting config - sortColumn: null, - sortOrder: "ascending", - sortType: null, - - // Pagination config - paginate: true, - } - - // State of the fetch - store = writable({ - rows: [], - info: null, - schema: null, - loading: false, - loaded: false, - query: null, - pageNumber: 0, - cursor: null, - cursors: [], - }) - /** * Constructs a new DataFetch instance. * @param opts the fetch options */ constructor(opts) { + // API client + this.API = null + + // Feature flags + this.featureStore = writable({ + supportsSearch: false, + supportsSort: false, + supportsPagination: false, + }) + + // Config + this.options = { + datasource: null, + limit: 10, + + // Search config + filter: null, + query: null, + + // Sorting config + sortColumn: null, + sortOrder: "ascending", + sortType: null, + + // Pagination config + paginate: true, + } + + // State of the fetch + this.store = writable({ + rows: [], + info: null, + schema: null, + loading: false, + loaded: false, + query: null, + pageNumber: 0, + cursor: null, + cursors: [], + }) + // Merge options with their default values this.API = opts?.API this.options = { diff --git a/packages/frontend-core/src/utils/lucene.js b/packages/frontend-core/src/utils/lucene.js index 1221e20664..774ddbd834 100644 --- a/packages/frontend-core/src/utils/lucene.js +++ b/packages/frontend-core/src/utils/lucene.js @@ -121,7 +121,12 @@ export const buildLuceneQuery = filter => { query.allOr = true 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 if (!value) { return diff --git a/packages/sdk/package.json b/packages/sdk/package.json index 992b391dea..59bd24e4ca 100644 --- a/packages/sdk/package.json +++ b/packages/sdk/package.json @@ -1,6 +1,6 @@ { "name": "@budibase/sdk", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "description": "Budibase Public API SDK", "author": "Budibase", "license": "MPL-2.0", diff --git a/packages/server/package.json b/packages/server/package.json index 1997a3e1aa..f22e992557 100644 --- a/packages/server/package.json +++ b/packages/server/package.json @@ -1,7 +1,7 @@ { "name": "@budibase/server", "email": "hi@budibase.com", - "version": "2.0.14-alpha.1", + "version": "2.0.23", "description": "Budibase Web Server", "main": "src/index.ts", "repository": { @@ -77,11 +77,11 @@ "license": "GPL-3.0", "dependencies": { "@apidevtools/swagger-parser": "10.0.3", - "@budibase/backend-core": "2.0.14-alpha.1", - "@budibase/client": "2.0.14-alpha.1", - "@budibase/pro": "2.0.14-alpha.0", - "@budibase/string-templates": "2.0.14-alpha.1", - "@budibase/types": "2.0.14-alpha.1", + "@budibase/backend-core": "^2.0.23", + "@budibase/client": "^2.0.23", + "@budibase/pro": "2.0.23", + "@budibase/string-templates": "^2.0.23", + "@budibase/types": "^2.0.23", "@bull-board/api": "3.7.0", "@bull-board/koa": "3.9.4", "@elastic/elasticsearch": "7.10.0", diff --git a/packages/server/src/api/controllers/application.ts b/packages/server/src/api/controllers/application.ts index d7e2a8f0bd..9dde91b348 100644 --- a/packages/server/src/api/controllers/application.ts +++ b/packages/server/src/api/controllers/application.ts @@ -50,6 +50,7 @@ import { errors, events, migrations } from "@budibase/backend-core" import { App, Layout, Screen, MigrationType } from "@budibase/types" import { BASE_LAYOUT_PROP_IDS } from "../../constants/layouts" import { groups } from "@budibase/pro" +import { enrichPluginURLs } from "../../utilities/plugins" const URL_REGEX_SLASH = /\/|\\/g @@ -208,10 +209,13 @@ export const fetchAppDefinition = async (ctx: any) => { export const fetchAppPackage = async (ctx: any) => { const db = context.getAppDB() - const application = await db.get(DocumentType.APP_METADATA) + let application = await db.get(DocumentType.APP_METADATA) const layouts = await getLayouts() let screens = await getScreens() + // Enrich plugin URLs + application.usedPlugins = enrichPluginURLs(application.usedPlugins) + // Only filter screens if the user is not a builder if (!(ctx.user.builder && ctx.user.builder.global)) { const userRoleId = getUserRoleId(ctx) diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.js index 4fafaa546c..af52be8e26 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.js @@ -68,6 +68,7 @@ exports.buildSchemaFromDb = async function (ctx) { datasource.entities = tables } + setDefaultDisplayColumns(datasource) const dbResp = await db.put(datasource) datasource._rev = dbResp.rev @@ -78,6 +79,24 @@ exports.buildSchemaFromDb = async function (ctx) { 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. */ @@ -155,6 +174,7 @@ exports.save = async function (ctx) { const { tables, error } = await buildSchemaHelper(datasource) schemaError = error datasource.entities = tables + setDefaultDisplayColumns(datasource) } const dbResp = await db.put(datasource) @@ -238,19 +258,6 @@ const buildSchemaHelper = async datasource => { const connector = new Connector(datasource.config) 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 let error = null if (errors && Object.keys(errors).length > 0) { diff --git a/packages/server/src/api/controllers/public/rows.ts b/packages/server/src/api/controllers/public/rows.ts index 4daccd9542..67059ec2f5 100644 --- a/packages/server/src/api/controllers/public/rows.ts +++ b/packages/server/src/api/controllers/public/rows.ts @@ -52,14 +52,19 @@ export async function read(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 next() } export async function destroy(ctx: any, next: any) { + const { tableId } = ctx.params // 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) // destroy controller doesn't currently return the row as the body, need to adjust this // in the public API to be correct diff --git a/packages/server/src/api/controllers/public/utils.ts b/packages/server/src/api/controllers/public/utils.ts index d86eced9ba..6909db9628 100644 --- a/packages/server/src/api/controllers/public/utils.ts +++ b/packages/server/src/api/controllers/public/utils.ts @@ -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 * startsWith function. */ diff --git a/packages/server/src/api/controllers/query/index.ts b/packages/server/src/api/controllers/query/index.ts index f69653b720..5c09a2f3b6 100644 --- a/packages/server/src/api/controllers/query/index.ts +++ b/packages/server/src/api/controllers/query/index.ts @@ -240,6 +240,10 @@ async function execute( const { rows, pagination, extra } = await quotas.addQuery(runFn, { 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) { ctx.body = rows } else { diff --git a/packages/server/src/api/controllers/row/internalSearch.js b/packages/server/src/api/controllers/row/internalSearch.js index 3cf60fbcc0..051a55aa9f 100644 --- a/packages/server/src/api/controllers/row/internalSearch.js +++ b/packages/server/src/api/controllers/row/internalSearch.js @@ -145,7 +145,7 @@ class QueryBuilder { * @param options The preprocess options * @returns {string|*} */ - preprocess(value, { escape, lowercase, wrap } = {}) { + preprocess(value, { escape, lowercase, wrap, type } = {}) { const hasVersion = !!this.version // Determine if type needs wrapped const originalType = typeof value @@ -157,8 +157,11 @@ class QueryBuilder { if (escape && originalType === "string") { value = `${value}`.replace(/[ #+\-&|!(){}\]^"~*?:\\]/g, "\\$&") } + // Wrap in quotes - if (hasVersion && wrap) { + if (originalType === "string" && !isNaN(value) && !type) { + value = `"${value}"` + } else if (hasVersion && wrap) { value = originalType === "number" ? value : `"${value}"` } return value @@ -253,6 +256,7 @@ class QueryBuilder { value = builder.preprocess(value, { escape: true, lowercase: true, + type: "string", }) return `${key}:${value}*` }) @@ -281,6 +285,7 @@ class QueryBuilder { value = builder.preprocess(value, { escape: true, lowercase: true, + type: "fuzzy", }) return `${key}:${value}~` }) diff --git a/packages/server/src/api/controllers/static/index.ts b/packages/server/src/api/controllers/static/index.ts index 80116a21f5..08213c2cf8 100644 --- a/packages/server/src/api/controllers/static/index.ts +++ b/packages/server/src/api/controllers/static/index.ts @@ -1,3 +1,5 @@ +import { enrichPluginURLs } from "../../../utilities/plugins" + require("svelte/register") const send = require("koa-send") @@ -107,12 +109,13 @@ export const serveApp = async function (ctx: any) { if (!env.isJest()) { const App = require("./templates/BudibaseApp.svelte").default + const plugins = enrichPluginURLs(appInfo.usedPlugins) const { head, html, css } = App.render({ title: appInfo.name, production: env.isProd(), appId, clientLibPath: clientLibraryPath(appId, appInfo.version, ctx), - usedPlugins: appInfo.usedPlugins, + usedPlugins: plugins, }) const appHbs = loadHandlebarsFile(`${__dirname}/templates/app.hbs`) diff --git a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte index 4bf54f2c91..227f980896 100644 --- a/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte +++ b/packages/server/src/api/controllers/static/templates/BudibaseApp.svelte @@ -88,9 +88,7 @@ {#if usedPlugins?.length} {#each usedPlugins as plugin} - + {/each} {/if}