Merge branch 'master' of github.com:Budibase/budibase into develop

This commit is contained in:
Michael Drury 2022-10-01 15:44:11 +01:00
commit 69abe9c5db
36 changed files with 264 additions and 138 deletions

View File

@ -1,5 +1,5 @@
{ {
"version": "2.0.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/types": "^2.0.13",
"@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

@ -182,6 +182,11 @@ export const streamUpload = async (
...extra, ...extra,
ContentType: "application/javascript", ContentType: "application/javascript",
} }
} else if (filename?.endsWith(".svg")) {
extra = {
...extra,
ContentType: "image",
}
} }
const params = { const params = {

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.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@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

@ -1,6 +1,6 @@
{ {
"name": "@budibase/builder", "name": "@budibase/builder",
"version": "2.0.10-alpha.1", "version": "2.0.13",
"license": "GPL-3.0", "license": "GPL-3.0",
"private": true, "private": true,
"scripts": { "scripts": {
@ -71,10 +71,10 @@
} }
}, },
"dependencies": { "dependencies": {
"@budibase/bbui": "2.0.10-alpha.1", "@budibase/bbui": "^2.0.13",
"@budibase/client": "2.0.10-alpha.1", "@budibase/client": "^2.0.13",
"@budibase/frontend-core": "2.0.10-alpha.1", "@budibase/frontend-core": "^2.0.13",
"@budibase/string-templates": "2.0.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@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

@ -143,7 +143,10 @@ export const getComponentSettings = componentType => {
} }
// Ensure whole component name is used // Ensure whole component name is used
if (!componentType.startsWith("@budibase")) { if (
!componentType.startsWith("plugin/") &&
!componentType.startsWith("@budibase")
) {
componentType = `@budibase/standard-components/${componentType}` componentType = `@budibase/standard-components/${componentType}`
} }

View File

@ -243,18 +243,18 @@ export const getDatasourceForProvider = (asset, component) => {
return null return null
} }
// There are different types of setting which can be a datasource, for // For legacy compatibility, we need to be able to handle datasources that are
// example an actual datasource object, or a table ID string. // just strings. These are not generated any more, so could be removed in
// Convert the datasource setting into a proper datasource object so that // future.
// we can use it properly // TODO: remove at some point
if (datasourceSetting.type === "table") { const datasource = component[datasourceSetting?.key]
if (typeof datasource === "string") {
return { return {
tableId: component[datasourceSetting?.key], tableId: datasource,
type: "table", type: "table",
} }
} else {
return component[datasourceSetting?.key]
} }
return datasource
} }
/** /**

View File

@ -88,27 +88,12 @@ export const getFrontendStore = () => {
initialise: async pkg => { initialise: async pkg => {
const { layouts, screens, application, clientLibPath } = pkg const { layouts, screens, application, clientLibPath } = pkg
// Fetch component definitions. await store.actions.components.refreshDefinitions(application.appId)
// Allow errors to propagate.
const components = await API.fetchComponentLibDefinitions(
application.appId
)
// Filter out custom component keys so we can flag them
const customComponents = Object.keys(components).filter(name =>
name.startsWith("plugin/")
)
// Reset store state // Reset store state
store.update(state => ({ store.update(state => ({
...state, ...state,
libraries: application.componentLibraries, libraries: application.componentLibraries,
components,
customComponents,
clientFeatures: {
...INITIAL_FRONTEND_STATE.clientFeatures,
...components.features,
},
name: application.name, name: application.name,
description: application.description, description: application.description,
appId: application.appId, appId: application.appId,
@ -385,6 +370,29 @@ export const getFrontendStore = () => {
}, },
}, },
components: { components: {
refreshDefinitions: async appId => {
if (!appId) {
appId = get(store).appId
}
// Fetch definitions and filter out custom component definitions so we
// can flag them
const components = await API.fetchComponentLibDefinitions(appId)
const customComponents = Object.keys(components).filter(name =>
name.startsWith("plugin/")
)
// Update store
store.update(state => ({
...state,
components,
customComponents,
clientFeatures: {
...INITIAL_FRONTEND_STATE.clientFeatures,
...components.features,
},
}))
},
getDefinition: componentName => { getDefinition: componentName => {
if (!componentName) { if (!componentName) {
return null return null
@ -428,7 +436,7 @@ export const getFrontendStore = () => {
_id: Helpers.uuid(), _id: Helpers.uuid(),
_component: definition.component, _component: definition.component,
_styles: { normal: {}, hover: {}, active: {} }, _styles: { normal: {}, hover: {}, active: {} },
_instanceName: `New ${definition.name}`, _instanceName: `New ${definition.friendlyName || definition.name}`,
...cloneDeep(props), ...cloneDeep(props),
...extras, ...extras,
} }

View File

@ -13,7 +13,7 @@
customQueryIconColor, customQueryIconColor,
customQueryText, customQueryText,
} from "helpers/data/utils" } from "helpers/data/utils"
import { getIcon } from "./icons" import IntegrationIcon from "./IntegrationIcon.svelte"
import { notifications } from "@budibase/bbui" import { notifications } from "@budibase/bbui"
let openDataSources = [] let openDataSources = []
@ -123,10 +123,10 @@
on:iconClick={() => toggleNode(datasource)} on:iconClick={() => toggleNode(datasource)}
> >
<div class="datasource-icon" slot="icon"> <div class="datasource-icon" slot="icon">
<svelte:component <IntegrationIcon
this={getIcon(datasource.source, datasource.schema)} integrationType={datasource.source}
height="18" schema={datasource.schema}
width="18" size="18"
/> />
</div> </div>
{#if datasource._id !== BUDIBASE_INTERNAL_DB} {#if datasource._id !== BUDIBASE_INTERNAL_DB}

View File

@ -0,0 +1,32 @@
<script>
import { getIcon } from "./icons"
import CustomSVG from "components/common/CustomSVG.svelte"
import { admin } from "stores/portal"
export let integrationType
export let schema
export let size = "18"
$: objectStoreUrl = $admin.cloud ? "https://cdn.budi.live" : ""
$: pluginsUrl = `${objectStoreUrl}/plugins`
$: iconInfo = getIcon(integrationType, schema)
async function getSvgFromUrl(info) {
const url = `${pluginsUrl}/${info.url}`
const resp = await fetch(url, {
headers: {
["pragma"]: "no-cache",
["cache-control"]: "no-cache",
},
})
return resp.text()
}
</script>
{#if iconInfo.icon}
<svelte:component this={iconInfo.icon} height={size} width={size} />
{:else if iconInfo.url}
{#await getSvgFromUrl(iconInfo) then retrievedSvg}
<CustomSVG {size} svgHtml={retrievedSvg} />
{/await}
{/if}

View File

@ -1,7 +1,7 @@
<script> <script>
import { createEventDispatcher } from "svelte" import { createEventDispatcher } from "svelte"
import { Heading, Detail } from "@budibase/bbui" import { Heading, Detail } from "@budibase/bbui"
import { getIcon } from "../icons" import IntegrationIcon from "../IntegrationIcon.svelte"
export let integration export let integration
export let integrationType export let integrationType
@ -16,11 +16,7 @@
class="item hoverable" class="item hoverable"
> >
<div class="item-body" class:with-type={!!schema.type}> <div class="item-body" class:with-type={!!schema.type}>
<svelte:component <IntegrationIcon {integrationType} {schema} size="25" />
this={getIcon(integrationType, schema)}
height="20"
width="20"
/>
<div class="text"> <div class="text">
<Heading size="XXS">{schema.friendlyName}</Heading> <Heading size="XXS">{schema.friendlyName}</Heading>
{#if schema.type} {#if schema.type}

View File

@ -16,6 +16,8 @@ import Firebase from "./Firebase.svelte"
import Redis from "./Redis.svelte" import Redis from "./Redis.svelte"
import Snowflake from "./Snowflake.svelte" import Snowflake from "./Snowflake.svelte"
import Custom from "./Custom.svelte" import Custom from "./Custom.svelte"
import { integrations } from "stores/backend"
import { get } from "svelte/store"
const ICONS = { const ICONS = {
BUDIBASE: Budibase, BUDIBASE: Budibase,
@ -41,9 +43,12 @@ const ICONS = {
export default ICONS export default ICONS
export function getIcon(integrationType, schema) { export function getIcon(integrationType, schema) {
if (schema?.custom || !ICONS[integrationType]) { const integrationList = get(integrations)
return ICONS.CUSTOM if (integrationList[integrationType]?.iconUrl) {
return { url: integrationList[integrationType].iconUrl }
} else if (schema?.custom || !ICONS[integrationType]) {
return { icon: ICONS.CUSTOM }
} else { } else {
return ICONS[integrationType] return { icon: ICONS[integrationType] }
} }
} }

View File

@ -0,0 +1,23 @@
<script>
import { Helpers } from "@budibase/bbui"
export let size
export let svgHtml
function substituteSize(svg) {
if (svg.includes("height=")) {
svg = svg.replace(/height="[^"]+"/, `height="${size}"`)
}
if (svg.includes("width=")) {
svg = svg.replace(/width="[^"]+"/, `width="${size}"`)
}
if (svg.includes("id=")) {
const matches = svg.match(/id="([^"]+)"/g)
for (let match of matches) {
svg = svg.replace(new RegExp(match, "g"), Helpers.uuid())
}
}
return svg
}
</script>
{@html substituteSize(svgHtml)}

View File

@ -1,26 +1,28 @@
<script> <script>
import { Select } from "@budibase/bbui" import { Select } from "@budibase/bbui"
import { tables } from "stores/backend" import { createEventDispatcher } from "svelte"
import { tables as tablesStore } from "stores/backend"
export let value export let value
const dispatch = createEventDispatcher()
$: tables = $tablesStore.list.map(m => ({
label: m.name,
tableId: m._id,
type: "table",
}))
const onChange = e => {
const dataSource = tables?.find(x => x.tableId === e.detail)
dispatch("change", dataSource)
}
</script> </script>
<div> <Select
<Select extraThin secondary wide on:change {value}> on:change={onChange}
<option value="">Choose a table</option> value={value?.tableId}
{#each $tables.list as table} options={tables}
<option value={table._id}>{table.name}</option> getOptionValue={x => x.tableId}
{/each} getOptionLabel={x => x.label}
</Select> />
</div>
<style>
div {
flex: 1 1 auto;
display: flex;
flex-direction: row;
}
div :global(> *) {
flex: 1 1 auto;
}
</style>

View File

@ -198,6 +198,8 @@
block: "center", block: "center",
}) })
} }
} else if (type === "reload-plugin") {
await store.actions.components.refreshDefinitions()
} else { } else {
console.warn(`Client sent unknown event type: ${type}`) console.warn(`Client sent unknown event type: ${type}`)
} }

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/cli", "name": "@budibase/cli",
"version": "2.0.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/backend-core": "^2.0.13",
"@budibase/string-templates": "2.0.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@budibase/types": "2.0.10-alpha.1", "@budibase/types": "^2.0.13",
"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

@ -21,3 +21,5 @@ exports.AnalyticsEvents = {
} }
exports.POSTHOG_TOKEN = "phc_yGOn4i7jWKaCTapdGR6lfA4AvmuEQ2ijn5zAVSFYPlS" exports.POSTHOG_TOKEN = "phc_yGOn4i7jWKaCTapdGR6lfA4AvmuEQ2ijn5zAVSFYPlS"
exports.GENERATED_USER_EMAIL = "admin@admin.com"

View File

@ -1,17 +1,22 @@
const { success } = require("../utils") const { success } = require("../utils")
const { updateDockerComposeService } = require("./utils") const { updateDockerComposeService } = require("./utils")
const randomString = require("randomstring") const randomString = require("randomstring")
const { GENERATED_USER_EMAIL } = require("../constants")
exports.generateUser = async () => { exports.generateUser = async (password, silent) => {
const email = "admin@admin.com" const email = GENERATED_USER_EMAIL
const password = randomString.generate({ length: 6 }) if (!password) {
password = randomString.generate({ length: 6 })
}
updateDockerComposeService(service => { updateDockerComposeService(service => {
service.environment["BB_ADMIN_USER_EMAIL"] = email service.environment["BB_ADMIN_USER_EMAIL"] = email
service.environment["BB_ADMIN_USER_PASSWORD"] = password service.environment["BB_ADMIN_USER_PASSWORD"] = password
}) })
if (!silent) {
console.log( console.log(
success( success(
`User admin credentials configured, access with email: ${email} - password: ${password}` `User admin credentials configured, access with email: ${email} - password: ${password}`
) )
) )
} }
}

View File

@ -33,7 +33,7 @@ async function getInitConfig(type, isQuick, port) {
} }
exports.init = async opts => { exports.init = async opts => {
let type, isSingle, watchDir, genUser, port let type, isSingle, watchDir, genUser, port, silent
if (typeof opts === "string") { if (typeof opts === "string") {
type = opts type = opts
} else { } else {
@ -42,6 +42,7 @@ exports.init = async opts => {
watchDir = opts["watchPluginDir"] watchDir = opts["watchPluginDir"]
genUser = opts["genUser"] genUser = opts["genUser"]
port = opts["port"] port = opts["port"]
silent = opts["silent"]
} }
const isQuick = type === InitTypes.QUICK || type === InitTypes.DIGITAL_OCEAN const isQuick = type === InitTypes.QUICK || type === InitTypes.DIGITAL_OCEAN
await checkDockerConfigured() await checkDockerConfigured()
@ -60,14 +61,15 @@ exports.init = async opts => {
const config = await getInitConfig(type, isQuick, port) const config = await getInitConfig(type, isQuick, port)
if (!isSingle) { if (!isSingle) {
await downloadFiles() await downloadFiles()
await makeFiles.makeEnv(config) await makeFiles.makeEnv(config, silent)
} else { } else {
await makeFiles.makeSingleCompose(config) await makeFiles.makeSingleCompose(config, silent)
} }
if (watchDir) { if (watchDir) {
await watchPlugins(watchDir) await watchPlugins(watchDir, silent)
} }
if (genUser) { if (genUser) {
await generateUser() const inputPassword = typeof genUser === "string" ? genUser : null
await generateUser(inputPassword, silent)
} }
} }

View File

@ -89,7 +89,7 @@ module.exports.QUICK_CONFIG = {
port: 10000, port: 10000,
} }
async function make(path, contentsFn, inputs = {}) { async function make(path, contentsFn, inputs = {}, silent) {
const port = const port =
inputs.port || inputs.port ||
(await number( (await number(
@ -98,19 +98,21 @@ async function make(path, contentsFn, inputs = {}) {
)) ))
const fileContents = contentsFn(port) const fileContents = contentsFn(port)
fs.writeFileSync(path, fileContents) fs.writeFileSync(path, fileContents)
if (!silent) {
console.log( console.log(
success( success(
`Configuration has been written successfully - please check ${path} for more details.` `Configuration has been written successfully - please check ${path} for more details.`
) )
) )
} }
module.exports.makeEnv = async (inputs = {}) => {
return make(ENV_PATH, getEnv, inputs)
} }
module.exports.makeSingleCompose = async (inputs = {}) => { module.exports.makeEnv = async (inputs = {}, silent) => {
return make(COMPOSE_PATH, getSingleCompose, inputs) return make(ENV_PATH, getEnv, inputs, silent)
}
module.exports.makeSingleCompose = async (inputs = {}, silent) => {
return make(COMPOSE_PATH, getSingleCompose, inputs, silent)
} }
module.exports.getEnvProperty = property => { module.exports.getEnvProperty = property => {

View File

@ -3,7 +3,7 @@ const fs = require("fs")
const { error, success } = require("../utils") const { error, success } = require("../utils")
const { updateDockerComposeService } = require("./utils") const { updateDockerComposeService } = require("./utils")
exports.watchPlugins = async pluginPath => { exports.watchPlugins = async (pluginPath, silent) => {
const PLUGIN_PATH = "/plugins" const PLUGIN_PATH = "/plugins"
// get absolute path // get absolute path
pluginPath = resolve(pluginPath) pluginPath = resolve(pluginPath)
@ -28,7 +28,9 @@ exports.watchPlugins = async pluginPath => {
} }
service.volumes.push(`${pluginPath}:${PLUGIN_PATH}`) service.volumes.push(`${pluginPath}:${PLUGIN_PATH}`)
}) })
if (!silent) {
console.log( console.log(
success(`Docker compose configured to watch directory: ${pluginPath}`) success(`Docker compose configured to watch directory: ${pluginPath}`)
) )
} }
}

View File

@ -10,6 +10,7 @@ const { join } = require("path")
const { success, error, info, moveDirectory } = require("../utils") const { success, error, info, moveDirectory } = require("../utils")
const { captureEvent } = require("../events") const { captureEvent } = require("../events")
const fp = require("find-free-port") const fp = require("find-free-port")
const { GENERATED_USER_EMAIL } = require("../constants")
const { init: hostingInit } = require("../hosting/init") const { init: hostingInit } = require("../hosting/init")
const { start: hostingStart } = require("../hosting/start") const { start: hostingStart } = require("../hosting/start")
@ -147,14 +148,24 @@ async function watch() {
async function dev() { async function dev() {
const pluginDir = await questions.string("Directory to watch", "./") const pluginDir = await questions.string("Directory to watch", "./")
const [port] = await fp(10000) const [port] = await fp(10000)
const password = "admin"
await hostingInit({ await hostingInit({
init: InitTypes.QUICK, init: InitTypes.QUICK,
single: true, single: true,
watchPluginDir: pluginDir, watchPluginDir: pluginDir,
genUser: true, genUser: password,
port, port,
silent: true,
}) })
await hostingStart() await hostingStart()
console.log(success(`Configuration has been written to docker-compose.yaml`))
console.log(
success("Development environment started successfully - connect at: ") +
info(`http://localhost:${port}`)
)
console.log(success("Use the following credentials to login:"))
console.log(success("Email: ") + info(GENERATED_USER_EMAIL))
console.log(success("Password: ") + info(password))
} }
const command = new Command(`${CommandWords.PLUGIN}`) const command = new Command(`${CommandWords.PLUGIN}`)

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/client", "name": "@budibase/client",
"version": "2.0.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/bbui": "^2.0.13",
"@budibase/frontend-core": "2.0.10-alpha.1", "@budibase/frontend-core": "^2.0.13",
"@budibase/string-templates": "2.0.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@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

@ -98,6 +98,9 @@ const createBuilderStore = () => {
return state return state
}) })
} }
// Notify the builder so we can reload component definitions
dispatchEvent("reload-plugin")
}, },
} }
return { return {

View File

@ -1,13 +1,19 @@
import { builderStore, environmentStore } from "./stores/index.js" import {
builderStore,
environmentStore,
notificationStore,
} from "./stores/index.js"
import { get } from "svelte/store" import { get } from "svelte/store"
import { io } from "socket.io-client" import { io } from "socket.io-client"
let socket
export const initWebsocket = () => { export const initWebsocket = () => {
const { inBuilder, location } = get(builderStore) const { inBuilder, location } = get(builderStore)
const { cloud } = get(environmentStore) const { cloud } = get(environmentStore)
// Only connect when we're inside the builder preview, for now // Only connect when we're inside the builder preview, for now
if (!inBuilder || !location || cloud) { if (!inBuilder || !location || cloud || socket) {
return return
} }
@ -16,20 +22,20 @@ export const initWebsocket = () => {
const proto = tls ? "wss:" : "ws:" const proto = tls ? "wss:" : "ws:"
const host = location.hostname const host = location.hostname
const port = location.port || (tls ? 443 : 80) const port = location.port || (tls ? 443 : 80)
const socket = io(`${proto}//${host}:${port}`, { socket = io(`${proto}//${host}:${port}`, {
path: "/socket/client", path: "/socket/client",
// Cap reconnection attempts to 10 (total of 95 seconds before giving up) // Cap reconnection attempts to 3 (total of 15 seconds before giving up)
reconnectionAttempts: 10, reconnectionAttempts: 3,
// Delay initial reconnection attempt by 5 seconds // Delay reconnection attempt by 5 seconds
reconnectionDelay: 5000, reconnectionDelay: 5000,
// Then decrease to 10 second intervals reconnectionDelayMax: 5000,
reconnectionDelayMax: 10000, // Timeout after 4 seconds so we never stack requests
// Timeout after 5 seconds so we never stack requests timeout: 4000,
timeout: 5000,
}) })
// Event handlers // Event handlers
socket.on("plugin-update", data => { socket.on("plugin-update", data => {
builderStore.actions.updateUsedPlugin(data.name, data.hash) builderStore.actions.updateUsedPlugin(data.name, data.hash)
notificationStore.actions.info(`"${data.name}" plugin reloaded`)
}) })
} }

View File

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

View File

@ -8,10 +8,9 @@ export const buildRowEndpoints = API => ({
if (!tableId || !rowId) { if (!tableId || !rowId) {
return null return null
} }
const row = await API.get({ return await API.get({
url: `/api/${tableId}/rows/${rowId}`, url: `/api/${tableId}/rows/${rowId}`,
}) })
return (await API.enrichRows([row], tableId))[0]
}, },
/** /**

View File

@ -1,6 +1,6 @@
{ {
"name": "@budibase/sdk", "name": "@budibase/sdk",
"version": "2.0.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/backend-core": "^2.0.13",
"@budibase/client": "2.0.10-alpha.1", "@budibase/client": "^2.0.13",
"@budibase/pro": "2.0.10-alpha.0", "@budibase/pro": "2.0.13",
"@budibase/string-templates": "2.0.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@budibase/types": "2.0.10-alpha.1", "@budibase/types": "^2.0.13",
"@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

@ -57,7 +57,11 @@ const INTEGRATIONS: { [key: string]: any } = {
} }
// optionally add oracle integration if the oracle binary can be installed // optionally add oracle integration if the oracle binary can be installed
if (process.arch && !process.arch.startsWith("arm")) { if (
process.arch &&
!process.arch.startsWith("arm") &&
oracle.integration.isInstalled()
) {
DEFINITIONS[SourceName.ORACLE] = oracle.schema DEFINITIONS[SourceName.ORACLE] = oracle.schema
INTEGRATIONS[SourceName.ORACLE] = oracle.integration INTEGRATIONS[SourceName.ORACLE] = oracle.integration
} }
@ -78,6 +82,9 @@ module.exports = {
...plugin.schema["schema"], ...plugin.schema["schema"],
custom: true, custom: true,
} }
if (plugin.iconUrl) {
pluginSchemas[sourceId].iconUrl = plugin.iconUrl
}
} }
} }
return { return {

View File

@ -15,17 +15,22 @@ import {
getSqlQuery, getSqlQuery,
SqlClient, SqlClient,
} from "./utils" } from "./utils"
import oracledb, { import Sql from "./base/sql"
import { FieldTypes } from "../constants"
import {
BindParameters, BindParameters,
Connection, Connection,
ConnectionAttributes, ConnectionAttributes,
ExecuteOptions, ExecuteOptions,
Result, Result,
} from "oracledb" } from "oracledb"
import Sql from "./base/sql" let oracledb: any
import { FieldTypes } from "../constants" try {
oracledb = require("oracledb")
oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT oracledb.outFormat = oracledb.OUT_FORMAT_OBJECT
} catch (err) {
console.log("ORACLEDB is not installed")
}
interface OracleConfig { interface OracleConfig {
host: string host: string
@ -183,6 +188,10 @@ class OracleIntegration extends Sql implements DatasourcePlus {
return parts.join(" || ") return parts.join(" || ")
} }
static isInstalled() {
return oracledb != null
}
/** /**
* Map the flat tabular columns and constraints data into a nested object * Map the flat tabular columns and constraints data into a nested object
*/ */

View File

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

@ -21,6 +21,7 @@ export interface Plugin extends Document {
name: string name: string
version: string version: string
jsUrl?: string jsUrl?: string
iconUrl?: string
source: PluginSource source: PluginSource
package: { [key: string]: any } package: { [key: string]: any }
hash: string hash: string

View File

@ -96,6 +96,7 @@ export interface Integration {
description: string description: string
friendlyName: string friendlyName: string
type?: string type?: string
iconUrl?: string
datasource: {} datasource: {}
query: { query: {
[key: string]: QueryDefinition [key: string]: QueryDefinition

View File

@ -1,7 +1,7 @@
{ {
"name": "@budibase/worker", "name": "@budibase/worker",
"email": "hi@budibase.com", "email": "hi@budibase.com",
"version": "2.0.10-alpha.1", "version": "2.0.13",
"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.10-alpha.1", "@budibase/backend-core": "^2.0.13",
"@budibase/pro": "2.0.10-alpha.0", "@budibase/pro": "2.0.13",
"@budibase/string-templates": "2.0.10-alpha.1", "@budibase/string-templates": "^2.0.13",
"@budibase/types": "2.0.10-alpha.1", "@budibase/types": "^2.0.13",
"@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",