1
0
Fork 0
mirror of synced 2024-07-05 22:40:39 +12:00

Fixing some typing that was added.

This commit is contained in:
mike12345567 2024-03-01 13:59:42 +00:00
commit ad0c1a94c9
31 changed files with 234 additions and 607 deletions

View file

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

View file

@ -11,6 +11,7 @@ import {
Document,
isDocument,
RowResponse,
RowValue,
} from "@budibase/types"
import { getCouchInfo } from "./connections"
import { directCouchUrlCall } from "./utils"
@ -222,7 +223,7 @@ export class DatabaseImpl implements Database {
})
}
async allDocs<T extends Document>(
async allDocs<T extends Document | RowValue>(
params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>> {
return this.performCall(db => {
@ -230,7 +231,7 @@ export class DatabaseImpl implements Database {
})
}
async sql<T>(sql: string): Promise<T> {
async sql<T extends Document>(sql: string): Promise<T> {
const dbName = this.name
const url = `/${dbName}/${SQLITE_DESIGN_DOC_ID}`
const response = await directCouchUrlCall({

View file

@ -1,5 +1,4 @@
import {
DocumentScope,
DocumentDestroyResponse,
DocumentInsertResponse,
DocumentBulkResponse,
@ -13,6 +12,7 @@ import {
DatabasePutOpts,
DatabaseQueryOpts,
Document,
RowValue,
} from "@budibase/types"
import tracer from "dd-trace"
import { Writable } from "stream"
@ -79,7 +79,7 @@ export class DDInstrumentedDatabase implements Database {
})
}
allDocs<T extends Document>(
allDocs<T extends Document | RowValue>(
params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>> {
return tracer.trace("db.allDocs", span => {
@ -147,7 +147,7 @@ export class DDInstrumentedDatabase implements Database {
})
}
sql<T>(sql: string): Promise<T> {
sql<T extends Document>(sql: string): Promise<T> {
return tracer.trace("db.sql", span => {
span?.addTags({ db_name: this.name })
return this.db.sql(sql)

View file

@ -116,7 +116,6 @@
$: pagerText = `Page ${currentPage} of ${totalPages}`
</script>
a11y-click-events-have-key-events
<div bind:this={buttonAnchor}>
<ActionButton on:click={dropdown.show}>
{displayValue}

View file

@ -12,11 +12,17 @@
hoverStore,
} from "stores/builder"
import ConfirmDialog from "components/common/ConfirmDialog.svelte"
import { Layout, Heading, Body, Icon, notifications } from "@budibase/bbui"
import {
ProgressCircle,
Layout,
Heading,
Body,
Icon,
notifications,
} from "@budibase/bbui"
import ErrorSVG from "@budibase/frontend-core/assets/error.svg?raw"
import { findComponent, findComponentPath } from "helpers/components"
import { isActive, goto } from "@roxi/routify"
import { ClientAppSkeleton } from "@budibase/frontend-core"
let iframe
let layout
@ -234,16 +240,8 @@
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="component-container">
{#if loading}
<div
class={`loading ${$builderStore.theme}`}
class:tablet={$previewStore.previewDevice === "tablet"}
class:mobile={$previewStore.previewDevice === "mobile"}
>
<ClientAppSkeleton
sideNav={$builderStore.navigation?.navigation === "Left"}
hideFooter
hideDevTools
/>
<div class="center">
<ProgressCircle />
</div>
{:else if error}
<div class="center error">
@ -260,6 +258,8 @@
bind:this={iframe}
src="/app/preview"
class:hidden={loading || error}
class:tablet={$previewStore.previewDevice === "tablet"}
class:mobile={$previewStore.previewDevice === "mobile"}
/>
<div
class="add-component"
@ -279,25 +279,6 @@
/>
<style>
.loading {
position: absolute;
container-type: inline-size;
width: 100%;
height: 100%;
border: 2px solid transparent;
box-sizing: border-box;
}
.loading.tablet {
width: calc(1024px + 6px);
max-height: calc(768px + 6px);
}
.loading.mobile {
width: calc(390px + 6px);
max-height: calc(844px + 6px);
}
.component-container {
grid-row-start: middle;
grid-column-start: middle;

View file

@ -1,22 +1,16 @@
<script>
import { onMount, onDestroy } from "svelte"
import { params, goto } from "@roxi/routify"
import { licensing, apps, auth, sideBarCollapsed } from "stores/portal"
import { apps, auth, sideBarCollapsed } from "stores/portal"
import { Link, Body, ActionButton } from "@budibase/bbui"
import { sdk } from "@budibase/shared-core"
import { API } from "api"
import ErrorSVG from "./ErrorSVG.svelte"
import { ClientAppSkeleton } from "@budibase/frontend-core"
$: app = $apps.find(app => app.appId === $params.appId)
$: iframeUrl = getIframeURL(app)
$: isBuilder = sdk.users.isBuilder($auth.user, app?.devId)
let loading = true
const getIframeURL = app => {
loading = true
if (app.status === "published") {
return `/app${app.url}`
}
@ -34,20 +28,6 @@
}
$: fetchScreens(app?.devId)
const receiveMessage = async message => {
if (message.data.type === "docLoaded") {
loading = false
}
}
onMount(() => {
window.addEventListener("message", receiveMessage)
})
onDestroy(() => {
window.removeEventListener("message", receiveMessage)
})
</script>
<div class="container">
@ -98,17 +78,7 @@
</Body>
</div>
{:else}
<div class:hide={!loading} class="loading">
<div class={`loadingThemeWrapper ${app.theme}`}>
<ClientAppSkeleton
noAnimation
hideDevTools={app?.status === "published"}
sideNav={app?.navigation.navigation === "Left"}
hideFooter={$licensing.brandingEnabled}
/>
</div>
</div>
<iframe class:hide={loading} src={iframeUrl} title={app.name} />
<iframe src={iframeUrl} title={app.name} />
{/if}
</div>
@ -130,23 +100,6 @@
flex: 0 0 50px;
}
.loading {
height: 100%;
border: 1px solid var(--spectrum-global-color-gray-300);
border-radius: var(--spacing-s);
overflow: hidden;
}
.loadingThemeWrapper {
height: 100%;
container-type: inline-size;
}
.hide {
visibility: hidden;
height: 0;
border: none;
}
iframe {
flex: 1 1 auto;
border-radius: var(--spacing-s);

View file

@ -80,18 +80,11 @@
}
}
let fontsLoaded = false
// Load app config
onMount(async () => {
document.fonts.ready.then(() => {
fontsLoaded = true
})
await initialise()
await authStore.actions.fetchUser()
dataLoaded = true
if (get(builderStore).inBuilder) {
builderStore.actions.notifyLoaded()
} else {
@ -100,12 +93,6 @@
})
}
})
$: {
if (dataLoaded && fontsLoaded) {
document.getElementById("clientAppSkeletonLoader")?.remove()
}
}
</script>
<svelte:head>
@ -116,140 +103,140 @@
{/if}
</svelte:head>
<div
id="spectrum-root"
lang="en"
dir="ltr"
class="spectrum spectrum--medium {$themeStore.baseTheme} {$themeStore.theme}"
class:builder={$builderStore.inBuilder}
class:show={fontsLoaded && dataLoaded}
>
<DeviceBindingsProvider>
<UserBindingsProvider>
<StateBindingsProvider>
<RowSelectionProvider>
<QueryParamsProvider>
<!-- Settings bar can be rendered outside of device preview -->
<!-- Key block needs to be outside the if statement or it breaks -->
{#key $builderStore.selectedComponentId}
{#if $builderStore.inBuilder}
<SettingsBar />
{/if}
{/key}
<!-- Clip boundary for selection indicators -->
<div
id="clip-root"
class:preview={$builderStore.inBuilder}
class:tablet-preview={$builderStore.previewDevice === "tablet"}
class:mobile-preview={$builderStore.previewDevice === "mobile"}
>
<!-- Actual app -->
<div id="app-root">
{#if showDevTools}
<DevToolsHeader />
{#if dataLoaded}
<div
id="spectrum-root"
lang="en"
dir="ltr"
class="spectrum spectrum--medium {$themeStore.baseTheme} {$themeStore.theme}"
class:builder={$builderStore.inBuilder}
>
<DeviceBindingsProvider>
<UserBindingsProvider>
<StateBindingsProvider>
<RowSelectionProvider>
<QueryParamsProvider>
<!-- Settings bar can be rendered outside of device preview -->
<!-- Key block needs to be outside the if statement or it breaks -->
{#key $builderStore.selectedComponentId}
{#if $builderStore.inBuilder}
<SettingsBar />
{/if}
{/key}
<div id="app-body">
{#if permissionError}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
You don't have permission to use this app
</Heading>
<Body size="S">
Ask your administrator to grant you access
</Body>
</Layout>
</div>
{:else if !$screenStore.activeLayout}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
Something went wrong rendering your app
</Heading>
<Body size="S">
Get in touch with support if this issue persists
</Body>
</Layout>
</div>
{:else if embedNoScreens}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
This Budibase app is not publicly accessible
</Heading>
</Layout>
</div>
{:else}
<CustomThemeWrapper>
{#key $screenStore.activeLayout._id}
<Component
isLayout
instance={$screenStore.activeLayout.props}
/>
{/key}
<!--
Flatpickr needs to be inside the theme wrapper.
It also needs its own container because otherwise it hijacks
key events on the whole page. It is painful to work with.
-->
<div id="flatpickr-root" />
<!-- Modal container to ensure they sit on top -->
<div class="modal-container" />
<!-- Layers on top of app -->
<NotificationDisplay />
<ConfirmationDisplay />
<PeekScreenDisplay />
</CustomThemeWrapper>
<!-- Clip boundary for selection indicators -->
<div
id="clip-root"
class:preview={$builderStore.inBuilder}
class:tablet-preview={$builderStore.previewDevice === "tablet"}
class:mobile-preview={$builderStore.previewDevice === "mobile"}
>
<!-- Actual app -->
<div id="app-root">
{#if showDevTools}
<DevToolsHeader />
{/if}
{#if showDevTools}
<DevTools />
<div id="app-body">
{#if permissionError}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
You don't have permission to use this app
</Heading>
<Body size="S">
Ask your administrator to grant you access
</Body>
</Layout>
</div>
{:else if !$screenStore.activeLayout}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
Something went wrong rendering your app
</Heading>
<Body size="S">
Get in touch with support if this issue persists
</Body>
</Layout>
</div>
{:else if embedNoScreens}
<div class="error">
<Layout justifyItems="center" gap="S">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html ErrorSVG}
<Heading size="L">
This Budibase app is not publicly accessible
</Heading>
</Layout>
</div>
{:else}
<CustomThemeWrapper>
{#key $screenStore.activeLayout._id}
<Component
isLayout
instance={$screenStore.activeLayout.props}
/>
{/key}
<!--
Flatpickr needs to be inside the theme wrapper.
It also needs its own container because otherwise it hijacks
key events on the whole page. It is painful to work with.
-->
<div id="flatpickr-root" />
<!-- Modal container to ensure they sit on top -->
<div class="modal-container" />
<!-- Layers on top of app -->
<NotificationDisplay />
<ConfirmationDisplay />
<PeekScreenDisplay />
</CustomThemeWrapper>
{/if}
{#if showDevTools}
<DevTools />
{/if}
</div>
{#if !$builderStore.inBuilder && licensing.logoEnabled()}
<FreeFooter />
{/if}
</div>
{#if !$builderStore.inBuilder && licensing.logoEnabled()}
<FreeFooter />
<!-- Preview and dev tools utilities -->
{#if $appStore.isDevApp}
<SelectionIndicator />
{/if}
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
<HoverIndicator />
{/if}
{#if $builderStore.inBuilder}
<DNDHandler />
<GridDNDHandler />
{/if}
</div>
<!-- Preview and dev tools utilities -->
{#if $appStore.isDevApp}
<SelectionIndicator />
{/if}
{#if $builderStore.inBuilder || $devToolsStore.allowSelection}
<HoverIndicator />
{/if}
{#if $builderStore.inBuilder}
<DNDHandler />
<GridDNDHandler />
{/if}
</div>
</QueryParamsProvider>
</RowSelectionProvider>
</StateBindingsProvider>
</UserBindingsProvider>
</DeviceBindingsProvider>
</div>
<KeyboardManager />
</QueryParamsProvider>
</RowSelectionProvider>
</StateBindingsProvider>
</UserBindingsProvider>
</DeviceBindingsProvider>
</div>
<KeyboardManager />
{/if}
<style>
#spectrum-root {
height: 0;
visibility: hidden;
padding: 0;
margin: 0;
overflow: hidden;
height: 100%;
width: 100%;
display: flex;
flex-direction: row;
@ -270,11 +257,6 @@
background-color: transparent;
}
#spectrum-root.show {
height: 100%;
visibility: visible;
}
#app-root {
overflow: hidden;
height: 100%;

View file

@ -13,7 +13,6 @@
<style>
.free-footer {
min-height: 51px;
flex: 0 0 auto;
padding: 16px 20px;
border-top: 1px solid var(--spectrum-global-color-gray-300);

View file

@ -1,244 +0,0 @@
<script>
export let sideNav = false
export let hideDevTools = false
export let hideFooter = false
export let noAnimation = false
</script>
<div class:sideNav id="clientAppSkeletonLoader" class="skeleton">
<div class="animation" class:noAnimation />
{#if !hideDevTools}
<div class="devTools" />
{/if}
<div class="main">
<div class="nav" />
<div class="body">
<div class="bodyVerticalPadding" />
<div class="bodyHorizontal">
<div class="bodyHorizontalPadding" />
<svg
class="svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
width="240"
height="256"
>
<mask id="mask">
<rect x="0" y="0" width="240" height="256" fill="white" />
<rect x="0" y="0" width="240" height="32" rx="6" fill="black" />
<rect x="0" y="56" width="240" height="32" rx="6" fill="black" />
<rect x="0" y="112" width="240" height="32" rx="6" fill="black" />
<rect x="0" y="168" width="240" height="32" rx="6" fill="black" />
<rect x="71" y="224" width="98" height="32" rx="6" fill="black" />
</mask>
<rect
x="0"
y="0"
width="240"
height="256"
fill="black"
mask="url(#mask)"
/>
</svg>
<div class="bodyHorizontalPadding" />
</div>
<div class="bodyVerticalPadding" />
</div>
</div>
{#if !hideFooter}
<div class="footer" />
{/if}
</div>
<style>
.skeleton {
position: relative;
height: 100%;
display: flex;
flex-direction: column;
border-radius: 4px;
overflow: hidden;
background-color: var(--spectrum-global-color-gray-200);
}
.animation {
position: absolute;
height: 100%;
width: 100%;
background: linear-gradient(
to right,
transparent 0%,
var(--spectrum-global-color-gray-300) 20%,
transparent 40%,
transparent 100%
);
animation-duration: 1.3s;
animation-fill-mode: forwards;
animation-iteration-count: infinite;
animation-name: shimmer;
animation-timing-function: linear;
}
.noAnimation {
animation-name: none;
background: transparent;
}
.devTools {
display: flex;
box-sizing: border-box;
background-color: black;
height: 60px;
padding: 1px 24px 1px 20px;
display: flex;
align-items: center;
z-index: 1;
flex-shrink: 0;
color: white;
mix-blend-mode: multiply;
background: rgb(0 0 0);
font-size: 30px;
font-family: Source Sans Pro;
-webkit-font-smoothing: antialiased;
}
.main {
height: 100%;
display: flex;
flex-direction: column;
}
@media (max-width: 720px) {
#clientAppSkeletonLoader .main {
flex-direction: column;
width: initial;
}
}
@container (max-width: 720px) {
#clientAppSkeletonLoader .main {
flex-direction: column;
width: initial;
}
}
.sideNav .main {
flex-direction: row;
width: 100%;
}
.nav {
flex-shrink: 0;
width: 100%;
height: 141px;
background-color: transparent;
}
@media (max-width: 720px) {
#clientAppSkeletonLoader .nav {
height: 61px;
width: initial;
}
}
@container (max-width: 720px) {
#clientAppSkeletonLoader .nav {
height: 61px;
width: initial;
}
}
.sideNav .nav {
height: 100%;
width: 251px;
}
.body {
z-index: 2;
display: flex;
flex-direction: column;
height: 100%;
position: relative;
}
@media (max-width: 720px) {
#clientAppSkeletonLoader .body {
width: initial;
height: 100%;
}
}
@container (max-width: 720px) {
#clientAppSkeletonLoader .body {
width: initial;
height: 100%;
}
}
.sideNav .body {
width: 100%;
height: initial;
}
.body :global(svg > rect) {
fill: var(--spectrum-alias-background-color-primary);
}
.body :global(svg) {
flex-shrink: 0;
}
.bodyHorizontal {
display: flex;
flex-shrink: 0;
}
.bodyHorizontalPadding {
height: 100%;
flex-grow: 1;
background-color: var(--spectrum-alias-background-color-primary);
}
.bodyVerticalPadding {
width: 100%;
flex-grow: 1;
background-color: var(--spectrum-alias-background-color-primary);
}
.footer {
flex-shrink: 0;
box-sizing: border-box;
z-index: 1;
height: 52px;
width: 100%;
}
@media (max-width: 720px) {
#clientAppSkeletonLoader .footer {
border-top: none;
}
}
@container (max-width: 720px) {
#clientAppSkeletonLoader .footer {
border-top: none;
}
}
.sideNav .footer {
border-top: 3px solid var(--spectrum-alias-background-color-primary);
}
@keyframes shimmer {
0% {
left: -170%;
}
100% {
left: 170%;
}
}
</style>

View file

@ -5,4 +5,3 @@ export { default as UserAvatar } from "./UserAvatar.svelte"
export { default as UserAvatars } from "./UserAvatars.svelte"
export { default as Updating } from "./Updating.svelte"
export { Grid } from "./grid"
export { default as ClientAppSkeleton } from "./ClientAppSkeleton.svelte"

View file

@ -17,8 +17,5 @@
--modal-background: var(--spectrum-global-color-gray-50);
--drop-shadow: rgba(0, 0, 0, 0.25) !important;
--spectrum-global-color-blue-100: rgba(35, 40, 50) !important;
--spectrum-alias-background-color-secondary: var(--spectrum-global-color-gray-75);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
}

View file

@ -50,7 +50,4 @@
--modal-background: var(--spectrum-global-color-gray-50);
--drop-shadow: rgba(0, 0, 0, 0.15) !important;
--spectrum-global-color-blue-100: rgb(56, 65, 84) !important;
--spectrum-alias-background-color-secondary: var(--spectrum-global-color-gray-75);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
}

View file

@ -52,7 +52,6 @@
"@budibase/pro": "0.0.0",
"@budibase/shared-core": "0.0.0",
"@budibase/string-templates": "0.0.0",
"@budibase/frontend-core": "0.0.0",
"@budibase/types": "0.0.0",
"@bull-board/api": "5.10.2",
"@bull-board/koa": "5.10.2",

View file

@ -15,10 +15,14 @@ import {
FieldType,
RelationshipFieldMetadata,
SourceName,
UpdateDatasourceRequest,
UpdateDatasourceResponse,
UserCtx,
VerifyDatasourceRequest,
VerifyDatasourceResponse,
Table,
RowValue,
DynamicVariable,
} from "@budibase/types"
import sdk from "../../sdk"
import { builderSocket } from "../../websockets"
@ -90,8 +94,10 @@ async function invalidateVariables(
existingDatasource: Datasource,
updatedDatasource: Datasource
) {
const existingVariables: any = existingDatasource.config?.dynamicVariables
const updatedVariables: any = updatedDatasource.config?.dynamicVariables
const existingVariables: DynamicVariable[] =
existingDatasource.config?.dynamicVariables || []
const updatedVariables: DynamicVariable[] =
updatedDatasource.config?.dynamicVariables || []
const toInvalidate = []
if (!existingVariables) {
@ -103,9 +109,9 @@ async function invalidateVariables(
toInvalidate.push(...existingVariables)
} else {
// invaldate changed / removed
existingVariables.forEach((existing: any) => {
existingVariables.forEach(existing => {
const unchanged = updatedVariables.find(
(updated: any) =>
updated =>
existing.name === updated.name &&
existing.queryId === updated.queryId &&
existing.value === updated.value
@ -118,24 +124,32 @@ async function invalidateVariables(
await invalidateDynamicVariables(toInvalidate)
}
export async function update(ctx: UserCtx<any, UpdateDatasourceResponse>) {
export async function update(
ctx: UserCtx<UpdateDatasourceRequest, UpdateDatasourceResponse>
) {
const db = context.getAppDB()
const datasourceId = ctx.params.datasourceId
const baseDatasource = await sdk.datasources.get(datasourceId)
const auth = baseDatasource.config?.auth
await invalidateVariables(baseDatasource, ctx.request.body)
const isBudibaseSource =
baseDatasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE
const dataSourceBody = isBudibaseSource
? { name: ctx.request.body?.name }
const dataSourceBody: Datasource = isBudibaseSource
? {
name: ctx.request.body?.name,
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
source: SourceName.BUDIBASE,
}
: ctx.request.body
let datasource: Datasource = {
...baseDatasource,
...sdk.datasources.mergeConfigs(dataSourceBody, baseDatasource),
}
// this block is specific to GSheets, if no auth set, set it back
const auth = baseDatasource.config?.auth
if (auth && !ctx.request.body.auth) {
// don't strip auth config from DB
datasource.config!.auth = auth
@ -204,7 +218,7 @@ async function destroyInternalTablesBySourceId(datasourceId: string) {
const db = context.getAppDB()
// Get all internal tables
const internalTables = await db.allDocs(
const internalTables = await db.allDocs<Table>(
getTableParams(null, {
include_docs: true,
})
@ -212,8 +226,8 @@ async function destroyInternalTablesBySourceId(datasourceId: string) {
// Filter by datasource and return the docs.
const datasourceTableDocs = internalTables.rows.reduce(
(acc: any, table: any) => {
if (table.doc.sourceId == datasourceId) {
(acc: Table[], table) => {
if (table.doc?.sourceId == datasourceId) {
acc.push(table.doc)
}
return acc
@ -254,9 +268,9 @@ export async function destroy(ctx: UserCtx) {
if (datasource.type === dbCore.BUDIBASE_DATASOURCE_TYPE) {
await destroyInternalTablesBySourceId(datasourceId)
} else {
const queries = await db.allDocs(getQueryParams(datasourceId))
const queries = await db.allDocs<RowValue>(getQueryParams(datasourceId))
await db.bulkDocs(
queries.rows.map((row: any) => ({
queries.rows.map(row => ({
_id: row.id,
_rev: row.value.rev,
_deleted: true,

View file

@ -1,7 +1,10 @@
import { getDefinition, getDefinitions } from "../../integrations"
import { SourceName, UserCtx } from "@budibase/types"
const DISABLED_EXTERNAL_INTEGRATIONS = [SourceName.AIRTABLE]
const DISABLED_EXTERNAL_INTEGRATIONS = [
SourceName.AIRTABLE,
SourceName.BUDIBASE,
]
export async function fetch(ctx: UserCtx) {
const definitions = await getDefinitions()

View file

@ -296,11 +296,12 @@ export async function fetchEnrichedRow(ctx: UserCtx) {
const tableId = utils.getTableId(ctx)
const rowId = ctx.params.rowId as string
// need table to work out where links go in row, as well as the link docs
const [table, row, links] = await Promise.all([
const [table, links] = await Promise.all([
sdk.tables.getTable(tableId),
utils.findRow(ctx, tableId, rowId),
linkRows.getLinkDocuments({ tableId, rowId, fieldName }),
])
let row = await utils.findRow(ctx, tableId, rowId)
row = await outputProcessing(table, row)
const linkVals = links as LinkDocumentValue[]
// look up the actual rows based on the ids

View file

@ -1,5 +1,7 @@
import { InvalidFileExtensions } from "@budibase/shared-core"
import AppComponent from "./templates/BudibaseApp.svelte"
import { join } from "../../../utilities/centralPath"
import * as uuid from "uuid"
import { ObjectStoreBuckets } from "../../../constants"
@ -23,11 +25,9 @@ import sdk from "../../../sdk"
import * as pro from "@budibase/pro"
import {
DocumentType,
UserCtx,
App,
Ctx,
ProcessAttachmentResponse,
Feature,
} from "@budibase/types"
import {
getAppMigrationVersion,
@ -36,61 +36,6 @@ import {
import send from "koa-send"
const getThemeVariables = (theme: string) => {
if (theme === "spectrum--lightest") {
return `
--spectrum-global-color-gray-50: rgb(255, 255, 255);
--spectrum-global-color-gray-200: rgb(244, 244, 244);
--spectrum-global-color-gray-300: rgb(234, 234, 234);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-50);
`
}
if (theme === "spectrum--light") {
return `
--spectrum-global-color-gray-50: rgb(255, 255, 255);
--spectrum-global-color-gray-200: rgb(234, 234, 234);
--spectrum-global-color-gray-300: rgb(225, 225, 225);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-50);
`
}
if (theme === "spectrum--dark") {
return `
--spectrum-global-color-gray-100: rgb(50, 50, 50);
--spectrum-global-color-gray-200: rgb(62, 62, 62);
--spectrum-global-color-gray-300: rgb(74, 74, 74);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
`
}
if (theme === "spectrum--darkest") {
return `
--spectrum-global-color-gray-100: rgb(30, 30, 30);
--spectrum-global-color-gray-200: rgb(44, 44, 44);
--spectrum-global-color-gray-300: rgb(57, 57, 57);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
`
}
if (theme === "spectrum--nord") {
return `
--spectrum-global-color-gray-100: #3b4252;
--spectrum-global-color-gray-200: #424a5c;
--spectrum-global-color-gray-300: #4c566a;
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
`
}
if (theme === "spectrum--midnight") {
return `
--hue: 220;
--sat: 10%;
--spectrum-global-color-gray-100: hsl(var(--hue), var(--sat), 17%);
--spectrum-global-color-gray-200: hsl(var(--hue), var(--sat), 20%);
--spectrum-global-color-gray-300: hsl(var(--hue), var(--sat), 24%);
--spectrum-alias-background-color-primary: var(--spectrum-global-color-gray-100);
`
}
}
export const toggleBetaUiFeature = async function (ctx: Ctx) {
const cookieName = `beta:${ctx.params.feature}`
@ -205,7 +150,7 @@ const requiresMigration = async (ctx: Ctx) => {
return requiresMigrations
}
export const serveApp = async function (ctx: UserCtx) {
export const serveApp = async function (ctx: Ctx) {
const needMigrations = await requiresMigration(ctx)
const bbHeaderEmbed =
@ -226,19 +171,9 @@ export const serveApp = async function (ctx: UserCtx) {
const appInfo = await db.get<any>(DocumentType.APP_METADATA)
let appId = context.getAppId()
const hideDevTools = !!ctx.params.appUrl
const sideNav = appInfo.navigation.navigation === "Left"
const hideFooter =
ctx?.user?.license?.features?.includes(Feature.BRANDING) || false
const themeVariables = getThemeVariables(appInfo?.theme)
if (!env.isJest()) {
const plugins = objectStore.enrichPluginURLs(appInfo.usedPlugins)
const { head, html, css } = AppComponent.render({
hideDevTools,
sideNav,
hideFooter,
metaImage:
branding?.metaImageUrl ||
"https://res.cloudinary.com/daog6scxm/image/upload/v1698759482/meta-images/plain-branded-meta-image-coral_ocxmgu.png",
@ -263,7 +198,7 @@ export const serveApp = async function (ctx: UserCtx) {
ctx.body = await processString(appHbs, {
head,
body: html,
css: `:root{${themeVariables}} ${css.code}`,
style: css.code,
appId,
embedded: bbHeaderEmbed,
})

View file

@ -1,6 +1,4 @@
<script>
import ClientAppSkeleton from "@budibase/frontend-core/src/components/ClientAppSkeleton.svelte"
export let title = ""
export let favicon = ""
@ -11,10 +9,6 @@
export let clientLibPath
export let usedPlugins
export let appMigrating
export let hideDevTools
export let sideNav
export let hideFooter
</script>
<svelte:head>
@ -102,7 +96,6 @@
</svelte:head>
<body id="app">
<ClientAppSkeleton {hideDevTools} {sideNav} {hideFooter} />
<div id="error">
{#if clientLibPath}
<h1>There was an error loading your app</h1>

View file

@ -1,12 +1,8 @@
<html>
<script>
document.fonts.ready.then(() => {
window.parent.postMessage({ type: "docLoaded" });
})
</script>
<head>
{{{head}}}
<style>{{{css}}}</style>
<style>{{{style}}}</style>
</head>
<script>

View file

@ -51,8 +51,8 @@ router
controller.deleteObjects
)
.get("/app/preview", authorized(BUILDER), controller.serveBuilderPreview)
.get("/app/:appUrl/:path*", controller.serveApp)
.get("/:appId/:path*", controller.serveApp)
.get("/app/:appUrl/:path*", controller.serveApp)
.post(
"/api/attachments/:datasourceId/url",
authorized(PermissionType.TABLE, PermissionLevel.READ),

View file

@ -1,8 +1,8 @@
import {
DEFAULT_BB_DATASOURCE_ID,
DEFAULT_INVENTORY_TABLE_ID,
DEFAULT_EMPLOYEE_TABLE_ID,
DEFAULT_EXPENSES_TABLE_ID,
DEFAULT_INVENTORY_TABLE_ID,
DEFAULT_JOBS_TABLE_ID,
} from "../../constants"
import { importToRows } from "../../api/controllers/table/utils"
@ -15,19 +15,21 @@ import { expensesImport } from "./expensesImport"
import { db as dbCore } from "@budibase/backend-core"
import {
AutoFieldSubType,
Datasource,
FieldType,
RelationshipType,
Row,
SourceName,
Table,
TableSchema,
TableSourceType,
} from "@budibase/types"
const defaultDatasource = {
const defaultDatasource: Datasource = {
_id: DEFAULT_BB_DATASOURCE_ID,
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
name: "Sample Data",
source: "BUDIBASE",
source: SourceName.BUDIBASE,
config: {},
}

View file

@ -1,13 +1,15 @@
import newid from "./newid"
import { db as dbCore } from "@budibase/backend-core"
import {
FieldType,
DatabaseQueryOpts,
Datasource,
DocumentType,
FieldSchema,
RelationshipFieldMetadata,
VirtualDocumentType,
FieldType,
INTERNAL_TABLE_SOURCE_ID,
DatabaseQueryOpts,
RelationshipFieldMetadata,
SourceName,
VirtualDocumentType,
} from "@budibase/types"
export { DocumentType, VirtualDocumentType } from "@budibase/types"
@ -20,11 +22,11 @@ export const enum AppStatus {
DEPLOYED = "published",
}
export const BudibaseInternalDB = {
export const BudibaseInternalDB: Datasource = {
_id: INTERNAL_TABLE_SOURCE_ID,
type: dbCore.BUDIBASE_DATASOURCE_TYPE,
name: "Budibase DB",
source: "BUDIBASE",
source: SourceName.BUDIBASE,
config: {},
}

View file

@ -37,6 +37,7 @@ const DEFINITIONS: Record<SourceName, Integration | undefined> = {
[SourceName.REDIS]: redis.schema,
[SourceName.SNOWFLAKE]: snowflake.schema,
[SourceName.ORACLE]: undefined,
[SourceName.BUDIBASE]: undefined,
}
const INTEGRATIONS: Record<SourceName, any> = {
@ -56,6 +57,7 @@ const INTEGRATIONS: Record<SourceName, any> = {
[SourceName.REDIS]: redis.integration,
[SourceName.SNOWFLAKE]: snowflake.integration,
[SourceName.ORACLE]: undefined,
[SourceName.BUDIBASE]: undefined,
}
// optionally add oracle integration if the oracle binary can be installed

View file

@ -85,7 +85,9 @@ async function getImportableDocuments(db: Database) {
const docPromises = []
for (let docType of DocumentTypesToImport) {
docPromises.push(
db.allDocs(dbCore.getDocParams(docType, null, { include_docs: true }))
db.allDocs<Document>(
dbCore.getDocParams(docType, null, { include_docs: true })
)
)
}
// map the responses to the document itself

View file

@ -229,7 +229,7 @@ export async function removeSecretSingle(datasource: Datasource) {
}
export function mergeConfigs(update: Datasource, old: Datasource) {
if (!update.config) {
if (!update.config || !old.config) {
return update
}
// specific to REST datasources, fix the auth configs again if required

View file

@ -32,9 +32,7 @@ export interface FetchDatasourceInfoResponse {
tableNames: string[]
}
export interface UpdateDatasourceRequest extends Datasource {
datasource: Datasource
}
export interface UpdateDatasourceRequest extends Datasource {}
export interface BuildSchemaFromSourceRequest {
tablesFilter?: string[]

View file

@ -6,6 +6,9 @@ export interface Datasource extends Document {
type: string
name?: string
source: SourceName
// this is a googlesheets specific property which
// can be found in the GSheets schema - pertains to SSO creds
auth?: { type: string }
// the config is defined by the schema
config?: Record<string, any>
plus?: boolean
@ -36,6 +39,12 @@ export interface RestAuthConfig {
config: RestBasicAuthConfig | RestBearerAuthConfig
}
export interface DynamicVariable {
name: string
queryId: string
value: string
}
export interface RestConfig {
url: string
rejectUnauthorized: boolean
@ -47,11 +56,5 @@ export interface RestConfig {
staticVariables: {
[key: string]: string
}
dynamicVariables: [
{
name: string
queryId: string
value: string
}
]
dynamicVariables: DynamicVariable[]
}

View file

@ -5,15 +5,15 @@ export interface RowValue {
deleted: boolean
}
export interface RowResponse<T extends Document> {
export interface RowResponse<T extends Document | RowValue> {
id: string
key: string
error: string
value: T | RowValue
value: T
doc?: T
}
export interface AllDocsResponse<T extends Document> {
export interface AllDocsResponse<T extends Document | RowValue> {
offset: number
total_rows: number
rows: RowResponse<T>[]

View file

@ -57,6 +57,7 @@ export enum SourceName {
FIRESTORE = "FIRESTORE",
REDIS = "REDIS",
SNOWFLAKE = "SNOWFLAKE",
BUDIBASE = "BUDIBASE",
}
export enum IncludeRelationship {

View file

@ -1,5 +1,11 @@
import type Nano from "@budibase/nano"
import { AllDocsResponse, AnyDocument, Document, ViewTemplateOpts } from "../"
import {
AllDocsResponse,
AnyDocument,
Document,
RowValue,
ViewTemplateOpts,
} from "../"
import { Writable } from "stream"
export enum SearchIndex {
@ -135,8 +141,8 @@ export interface Database {
opts?: DatabasePutOpts
): Promise<Nano.DocumentInsertResponse>
bulkDocs(documents: AnyDocument[]): Promise<Nano.DocumentBulkResponse[]>
sql<T>(sql: string): Promise<T>
allDocs<T extends Document>(
sql<T extends Document>(sql: string): Promise<T>
allDocs<T extends Document | RowValue>(
params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>>
query<T extends Document>(

View file

@ -17,6 +17,12 @@ const { nodeExternalsPlugin } = require("esbuild-node-externals")
const svelteCompilePlugin = {
name: 'svelteCompile',
setup(build) {
// This resolve handler is necessary to bundle the Svelte runtime into the the final output,
// otherwise the bundled script will attempt to resolve it at runtime
build.onResolve({ filter: /svelte\/internal/ }, async () => {
return { path: `${process.cwd()}/../../node_modules/svelte/src/runtime/internal/ssr.js` }
})
// Compiles `.svelte` files into JS classes so that they can be directly imported into our
// Typescript packages
build.onLoad({ filter: /\.svelte$/ }, async (args) => {
@ -31,7 +37,7 @@ const svelteCompilePlugin = {
contents: js.code,
// The loader this is passed to, basically how the above provided content is "treated",
// the contents provided above will be transpiled and bundled like any other JS file.
loader: 'js',
loader: 'js',
// Where to resolve any imports present in the loaded file
resolveDir: dir
}
@ -74,11 +80,11 @@ async function runBuild(entry, outfile) {
plugins: [
svelteCompilePlugin,
TsconfigPathsPlugin({ tsconfig: tsconfigPathPluginContent }),
nodeExternalsPlugin({
allowList: ["@budibase/frontend-core", "svelte"]
}),
nodeExternalsPlugin(),
],
preserveSymlinks: true,
loader: {
},
metafile: true,
external: [
"deasync",