Merge branch 'feature/sql-relationships' of github.com:Budibase/budibase into feature/opinionated-relationships-ui

This commit is contained in:
Martin McKeaveney 2021-07-01 14:14:52 +01:00
commit d801f49ac4
24 changed files with 166 additions and 100 deletions

View File

@ -152,7 +152,7 @@ The HTML and CSS for your apps runtime pages, as well as the budibase client lib
#### Backend
The backend schema, tables and rows are stored using PouchDB when developing locally, and in [CouchDB](https://pouchdb.com/) when running in production.
For the backend we run [Redis](https://redis.io/), [CouchDB](https://couchdb.apache.org/), [MinIO](https://min.io/) and [Envoy](https://www.envoyproxy.io/) in Docker compose. This means that to develop Budibase you will need Docker and Docker compose installed. The backend services are then ran separately as Node services with nodemon so that they can be debugged outside of Docker.
### Publishing Budibase to NPM

View File

@ -20,8 +20,8 @@ jobs:
with:
node-version: 12.x
- run: yarn
- run: yarn lint
- run: yarn bootstrap
- run: yarn lint
- run: yarn build
- run: yarn test

View File

@ -1,5 +1,5 @@
{
"version": "0.9.65",
"version": "0.9.69",
"npmClient": "yarn",
"packages": [
"packages/*"

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/auth",
"version": "0.9.65",
"version": "0.9.69",
"description": "Authentication middlewares for budibase builder and apps",
"main": "src/index.js",
"author": "Budibase",

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/bbui",
"description": "A UI solution used in the different Budibase projects.",
"version": "0.9.65",
"version": "0.9.69",
"license": "AGPL-3.0",
"svelte": "src/index.js",
"module": "dist/bbui.es.js",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/builder",
"version": "0.9.65",
"version": "0.9.69",
"license": "AGPL-3.0",
"private": true,
"scripts": {
@ -65,10 +65,10 @@
}
},
"dependencies": {
"@budibase/bbui": "^0.9.65",
"@budibase/client": "^0.9.65",
"@budibase/bbui": "^0.9.69",
"@budibase/client": "^0.9.69",
"@budibase/colorpicker": "1.1.2",
"@budibase/string-templates": "^0.9.65",
"@budibase/string-templates": "^0.9.69",
"@sentry/browser": "5.19.1",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",

View File

@ -284,7 +284,7 @@ export const background = {
export const border = {
label: "Border",
columns: "auto 1fr",
columns: "1fr 1fr",
settings: [
{
label: "Color",
@ -295,17 +295,31 @@ export const border = {
label: "Width",
key: "border-width",
control: Select,
column: "1 / 2",
placeholder: "None",
options: [
{ label: "Small", value: "1px" },
{ label: "Medium", value: "2px" },
{ label: "Large", value: "4px" },
],
},
{
label: "Style",
key: "border-style",
control: Select,
column: "2 / 3",
placeholder: "None",
options: [
{ label: "Solid", value: "solid" },
{ label: "Dotted", value: "dotted" },
{ label: "Dashed", value: "dashed" },
],
},
{
label: "Radius",
key: "border-radius",
control: Select,
column: "1 / 3",
placeholder: "None",
options: [
{ label: "Small", value: "0.25rem" },
{ label: "Medium", value: "0.5rem" },
@ -317,7 +331,7 @@ export const border = {
label: "Shadow",
key: "box-shadow",
control: Select,
column: "1 / 3",
placeholder: "None",
options: [
{
label: "Small",

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/cli",
"version": "0.9.65",
"version": "0.9.69",
"description": "Budibase CLI, for developers, self hosting and migrations.",
"main": "src/index.js",
"bin": {

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/client",
"version": "0.9.65",
"version": "0.9.69",
"license": "MPL-2.0",
"module": "dist/budibase-client.js",
"main": "dist/budibase-client.js",
@ -18,9 +18,9 @@
"dev:builder": "rollup -cw"
},
"dependencies": {
"@budibase/bbui": "^0.9.65",
"@budibase/standard-components": "^0.9.65",
"@budibase/string-templates": "^0.9.65",
"@budibase/bbui": "^0.9.69",
"@budibase/standard-components": "^0.9.69",
"@budibase/string-templates": "^0.9.69",
"regexparam": "^1.3.0",
"shortid": "^2.2.15",
"svelte-spa-router": "^3.0.5"

View File

@ -34,11 +34,6 @@ export const styleable = (node, styles = {}) => {
baseStyles.overflow = "hidden"
}
// Append border-style css if border-width is specified
if (newStyles.normal?.["border-width"]) {
baseStyles["border-style"] = "solid"
}
const componentId = newStyles.id
const customStyles = newStyles.custom || ""
const normalStyles = { ...baseStyles, ...newStyles.normal }

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/server",
"email": "hi@budibase.com",
"version": "0.9.65",
"version": "0.9.69",
"description": "Budibase Web Server",
"main": "src/index.js",
"repository": {
@ -59,9 +59,9 @@
"author": "Budibase",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@budibase/auth": "^0.9.65",
"@budibase/client": "^0.9.65",
"@budibase/string-templates": "^0.9.65",
"@budibase/auth": "^0.9.69",
"@budibase/client": "^0.9.69",
"@budibase/string-templates": "^0.9.69",
"@elastic/elasticsearch": "7.10.0",
"@koa/router": "8.0.0",
"@sendgrid/mail": "7.1.1",
@ -114,14 +114,14 @@
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/preset-env": "^7.14.4",
"@budibase/standard-components": "^0.9.65",
"@budibase/standard-components": "^0.9.69",
"@jest/test-sequencer": "^24.8.0",
"@types/bull": "^3.15.1",
"@types/jest": "^26.0.23",
"@types/koa": "^2.13.3",
"@types/koa-router": "^7.4.2",
"@types/node": "^15.12.4",
"@typescript-eslint/parser": "^4.28.0",
"@typescript-eslint/parser": "4.28.0",
"babel-jest": "^27.0.2",
"copyfiles": "^2.4.1",
"docker-compose": "^0.23.6",

View File

@ -1,5 +1,5 @@
const { makeExternalQuery } = require("./utils")
const { DataSourceOperation, SortDirection } = require("../../../constants")
const { DataSourceOperation, SortDirection, FieldTypes } = require("../../../constants")
const { getAllExternalTables } = require("../table/utils")
const {
breakExternalTableId,
@ -19,10 +19,12 @@ async function handleRequest(
appId,
operation,
tableId,
{ id, row, filters, sort, paginate, fullDocs } = {}
{ id, row, filters, sort, paginate, tables } = {}
) {
let { datasourceId, tableName } = breakExternalTableId(tableId)
const tables = await getAllExternalTables(appId, datasourceId)
if (!tables) {
tables = await getAllExternalTables(appId, datasourceId)
}
const table = tables[tableName]
if (!table) {
throw `Unable to process query, table "${tableName}" not defined.`
@ -83,8 +85,7 @@ async function handleRequest(
response,
table,
relationships,
tables,
fullDocs
tables
)
// if reading it'll just be an array of rows, return whole thing
return operation === DataSourceOperation.READ && Array.isArray(response)
@ -239,15 +240,43 @@ exports.fetchEnrichedRow = async ctx => {
const appId = ctx.appId
const id = ctx.params.rowId
const tableId = ctx.params.tableId
// TODO: this only enriches the full docs 1 layer deep, need to join those as well
const { datasourceId, tableName } = breakExternalTableId(tableId)
const tables = await getAllExternalTables(appId, datasourceId)
const response = await handleRequest(
appId,
DataSourceOperation.READ,
tableId,
{
id,
fullDocs: true,
tables,
}
)
return response ? response[0] : response
const table = tables[tableName]
const row = response[0]
// this seems like a lot of work, but basically we need to dig deeper for the enrich
// for a single row, there is probably a better way to do this with some smart multi-layer joins
for (let [fieldName, field] of Object.entries(table.schema)) {
if (field.type !== FieldTypes.LINK || !row[fieldName] || row[fieldName].length === 0) {
continue
}
const links = row[fieldName]
const linkedTableId = field.tableId
const linkedTable = tables[breakExternalTableId(linkedTableId).tableName]
// don't support composite keys right now
const linkedIds = links.map(link => breakRowIdField(link._id)[0])
row[fieldName] = await handleRequest(
appId,
DataSourceOperation.READ,
linkedTableId,
{
tables,
filters: {
oneOf: {
[linkedTable.primary]: linkedIds,
},
},
},
)
}
return row
}

View File

@ -80,8 +80,7 @@ exports.updateRelationshipColumns = (
row,
rows,
relationships,
allTables,
fullDocs
allTables
) => {
const columns = {}
for (let relationship of relationships) {
@ -91,12 +90,10 @@ exports.updateRelationshipColumns = (
}
let linked = basicProcessing(row, linkedTable)
// if not returning full docs then get the minimal links out
if (!fullDocs) {
const display = linkedTable.primaryDisplay
linked = {
primaryDisplay: display ? linked[display] : undefined,
_id: linked._id,
}
const display = linkedTable.primaryDisplay
linked = {
primaryDisplay: display ? linked[display] : undefined,
_id: linked._id,
}
columns[relationship.column] = linked
}
@ -116,8 +113,7 @@ exports.outputProcessing = (
rows,
table,
relationships,
allTables,
fullDocs
allTables
) => {
// if no rows this is what is returned? Might be PG only
if (rows[0].read === true) {
@ -132,8 +128,7 @@ exports.outputProcessing = (
row,
finalRows,
relationships,
allTables,
fullDocs
allTables
)
continue
}
@ -144,8 +139,7 @@ exports.outputProcessing = (
row,
finalRows,
relationships,
allTables,
fullDocs
allTables
)
}
return Object.values(finalRows)

View File

@ -1,3 +1,5 @@
import {breakExternalTableId} from "../../../integrations/utils"
const CouchDB = require("../../../db")
const csvParser = require("../../../utilities/csvParser")
const {

View File

@ -72,6 +72,9 @@ export interface SearchFilters {
notEmpty?: {
[key: string]: any
}
oneOf?: {
[key: string]: any[]
}
}
export interface RelationshipsJson {

View File

@ -30,6 +30,12 @@ function addFilters(
}
// if all or specified in filters, then everything is an or
const allOr = filters.allOr
if (filters.oneOf) {
iterate(filters.oneOf, (key, array) => {
const fnc = allOr ? "orWhereIn" : "whereIn"
query = query[fnc](key, array)
})
}
if (filters.string) {
iterate(filters.string, (key, value) => {
const fnc = allOr ? "orWhere" : "where"

View File

@ -1146,10 +1146,10 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
"@budibase/auth@^0.9.65":
version "0.9.65"
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.65.tgz#3ba3ae9dd04781674682bc3b612fba0c16c92a1a"
integrity sha512-WVNT69uLgpQYKrHclPApYnL0Jfg7gct1oCbziJWoNEisRgSLe+SjtduQDhn5R8SZcPdmP4xdhISwlrvI+tYJsw==
"@budibase/auth@^0.9.66":
version "0.9.66"
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-0.9.66.tgz#543eb6e0cbc0072d8567fdb5ce0f60a601e84f9f"
integrity sha512-hLVCzSmXk7X6oYpNQz06wYyXeN/eJP1AWKtfJfvUOCyE1zLDAxxkvk6UTnAZJ6Mj013QNjWfI9ohlncvY1vsmQ==
dependencies:
aws-sdk "^2.901.0"
bcryptjs "^2.4.3"
@ -1167,10 +1167,10 @@
uuid "^8.3.2"
zlib "^1.0.5"
"@budibase/bbui@^0.9.65":
version "0.9.65"
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.65.tgz#cdcfa418b79b27c10195b65a90c10f571b32ae70"
integrity sha512-DHhBe3e6kO5GiVpkOwjFReiBiXeIuOxFgKKxI6X5TIUGbnVzsM032ehcyH9QRxwMlwIIGjEA6CSKjxMreJ7sPA==
"@budibase/bbui@^0.9.66":
version "0.9.66"
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-0.9.66.tgz#aba79def0d90c2fcb322ae787c06b47f6c1c3814"
integrity sha512-2P7SFbrw5/E8g4eSZ4OBuJOMDQPyjZBTcZkGtMIP2BlGH3Pn6OilYrH9OmHhn0zebzFA4hGoRgrT2TOiMBRCrg==
dependencies:
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
"@spectrum-css/actionbutton" "^1.0.1"
@ -1215,14 +1215,14 @@
svelte-flatpickr "^3.1.0"
svelte-portal "^1.0.0"
"@budibase/client@^0.9.65":
version "0.9.65"
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.65.tgz#8ad5fb1400ddc620955d6bb12aad181ff56498a6"
integrity sha512-9Eo0xdCxqGxnn8s0RJq/Nx+WFK8SM+GWd0vKi55TuKC/Oj4X8qnRprpL5la83cQrRb2aGCk5/41IdETnwtTNGw==
"@budibase/client@^0.9.66":
version "0.9.66"
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-0.9.66.tgz#04a0838352169607fc005f9910e7c2d485fdbe06"
integrity sha512-2SJWAZjqi5DUdAJBYmyfKuCw1pHmgzdjEHgU0kP5MZpHxcllKcyQCTELRVFRebz74PR9GibjvNNUIexQQElEVQ==
dependencies:
"@budibase/bbui" "^0.9.65"
"@budibase/standard-components" "^0.9.65"
"@budibase/string-templates" "^0.9.65"
"@budibase/bbui" "^0.9.66"
"@budibase/standard-components" "^0.9.66"
"@budibase/string-templates" "^0.9.66"
regexparam "^1.3.0"
shortid "^2.2.15"
svelte-spa-router "^3.0.5"
@ -1259,12 +1259,12 @@
to-gfm-code-block "^0.1.1"
year "^0.2.1"
"@budibase/standard-components@^0.9.65":
version "0.9.65"
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.65.tgz#6c6b82160952ca1413777f303a915289c759e3f2"
integrity sha512-MIGQFmckV5KC3kurZTAHPrpw/dNXwd0sTzfva3f1NwpkZUVN/dovBnyrU3xmMULq2Aj2DfomUR/mCbTlKRBSMA==
"@budibase/standard-components@^0.9.66":
version "0.9.66"
resolved "https://registry.yarnpkg.com/@budibase/standard-components/-/standard-components-0.9.66.tgz#79ee98e0b5b71801360594b59966f203197eb6ae"
integrity sha512-iq+ninGbe5GqNRk8qxlgXXH7hgCFJ90+Xw1zhYRtIE//BmeGYHxEJjDTjG+7qSHPvp2ZB4KkLiD/y7/H0zwuEA==
dependencies:
"@budibase/bbui" "^0.9.65"
"@budibase/bbui" "^0.9.66"
"@spectrum-css/link" "^3.1.3"
"@spectrum-css/page" "^3.0.1"
"@spectrum-css/vars" "^3.0.1"
@ -1273,10 +1273,10 @@
svelte-apexcharts "^1.0.2"
svelte-flatpickr "^3.1.0"
"@budibase/string-templates@^0.9.65":
version "0.9.65"
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.65.tgz#63c9461284ee5f20be35a246082835b00e95672c"
integrity sha512-hD/NN1h+AQzNlr+OukwUAN9qqbFyH7EBLYNPD507ZAy0fiP+Z5+GgnjGeIkP8tZk8LDtVCcM2uSjyjG+X3UX7Q==
"@budibase/string-templates@^0.9.66":
version "0.9.66"
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-0.9.66.tgz#700145549f1636cb46f88b94ef23b3a064058b75"
integrity sha512-eFFBTTKlRpzNSNwKGOclRkXlrKr5UxV3sCU2QfskPXai4hx9RtD/LyKKSlLshVU1ZjwfTCor9cm7f/hhxRzuRA==
dependencies:
"@budibase/handlebars-helpers" "^0.11.4"
dayjs "^1.10.4"
@ -2613,7 +2613,7 @@
dependencies:
"@types/yargs-parser" "*"
"@typescript-eslint/parser@^4.28.0":
"@typescript-eslint/parser@4.28.0":
version "4.28.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-4.28.0.tgz#2404c16751a28616ef3abab77c8e51d680a12caa"
integrity sha512-7x4D22oPY8fDaOCvkuXtYYTQ6mTMmkivwEzS+7iml9F9VkHGbbZ3x4fHRwxAb5KeuSkLqfnYjs46tGx2Nour4A==

View File

@ -29,11 +29,11 @@
"keywords": [
"svelte"
],
"version": "0.9.65",
"version": "0.9.69",
"license": "MIT",
"gitHead": "d1836a898cab3f8ab80ee6d8f42be1a9eed7dcdc",
"dependencies": {
"@budibase/bbui": "^0.9.65",
"@budibase/bbui": "^0.9.69",
"@spectrum-css/link": "^3.1.3",
"@spectrum-css/page": "^3.0.1",
"@spectrum-css/vars": "^3.0.1",

View File

@ -19,12 +19,19 @@
// Add color styles to main styles object, otherwise the styleable helper
// overrides the color when it's passed as inline style.
$: styles = {
...$component.styles,
normal: {
...$component.styles?.normal,
color,
},
$: styles = enrichStyles($component.styles, color)
const enrichStyles = (styles, color) => {
if (!color) {
return styles
}
return {
...styles,
normal: {
...styles?.normal,
color,
},
}
}
</script>

View File

@ -23,12 +23,21 @@
// Add color styles to main styles object, otherwise the styleable helper
// overrides the color when it's passed as inline style.
$: styles = {
...$component.styles,
normal: {
...$component.styles?.normal,
color,
},
// Add color styles to main styles object, otherwise the styleable helper
// overrides the color when it's passed as inline style.
$: styles = enrichStyles($component.styles, color)
const enrichStyles = (styles, color) => {
if (!color) {
return styles
}
return {
...styles,
normal: {
...styles?.normal,
color,
},
}
}
</script>

View File

@ -19,12 +19,19 @@
// Add color styles to main styles object, otherwise the styleable helper
// overrides the color when it's passed as inline style.
$: styles = {
...$component.styles,
normal: {
...$component.styles?.normal,
color,
},
$: styles = enrichStyles($component.styles, color)
const enrichStyles = (styles, color) => {
if (!color) {
return styles
}
return {
...styles,
normal: {
...styles?.normal,
color,
},
}
}
</script>

View File

@ -1,6 +1,6 @@
{
"name": "@budibase/string-templates",
"version": "0.9.65",
"version": "0.9.69",
"description": "Handlebars wrapper for Budibase templating.",
"main": "src/index.cjs",
"module": "dist/bundle.mjs",

View File

@ -1,7 +1,7 @@
{
"name": "@budibase/worker",
"email": "hi@budibase.com",
"version": "0.9.65",
"version": "0.9.69",
"description": "Budibase background service",
"main": "src/index.js",
"repository": {
@ -21,8 +21,8 @@
"author": "Budibase",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@budibase/auth": "^0.9.65",
"@budibase/string-templates": "^0.9.65",
"@budibase/auth": "^0.9.69",
"@budibase/string-templates": "^0.9.69",
"@koa/router": "^8.0.0",
"aws-sdk": "^2.811.0",
"bcryptjs": "^2.4.3",

View File

@ -8,7 +8,7 @@ const CouchDB = require("../../../db")
exports.fetch = async ctx => {
// always use the dev apps as they'll be most up to date (true)
const apps = await getAllApps({ CouchDB, dev: true })
const apps = await getAllApps({ CouchDB, all: true })
const promises = []
for (let app of apps) {
// use dev app IDs