Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4f8cfe7
feat: improve SQL query editor experience
mohagan9 Jul 31, 2026
bac1683
chore: apply lint formatting
mohagan9 Jul 31, 2026
0eb8b41
Merge branch 'feature/v3' into feature/v3-sql-query
mohagan9 Aug 1, 2026
8ae8144
Merge pull request #149 from SuperToolMake/feature/v3-sql-query
mohagan9 Aug 1, 2026
39ea98c
Allow query viewer header controls to wrap to next line
mohagan9 Aug 1, 2026
2a008ef
feat: add workspace REST API queries
mohagan9 Aug 2, 2026
821b2ad
Merge branch 'main' into feature/v3
mohagan9 Aug 7, 2026
c48d63b
Merge branch 'main' into feature/v3
mohagan9 Aug 7, 2026
7376c4e
Merge branch 'main' into feature/v3
mohagan9 Aug 7, 2026
48e95f4
Merge branch 'feature/v3' into feature/v3-rest-query
mohagan9 Aug 7, 2026
380a11f
'Add config' navigates to APIs modal settings
mohagan9 Aug 7, 2026
722c39e
Add OAuth2 REST config
mohagan9 Aug 7, 2026
d1921ca
Refresh static variable list
mohagan9 Aug 7, 2026
b64ec94
lint
mohagan9 Aug 7, 2026
383bfbb
Remove maildev
mohagan9 Aug 7, 2026
1f18036
Add username/password fields for Basic auth headers
mohagan9 Aug 7, 2026
6aa8bed
Add jsdom dev dependency
mohagan9 Aug 7, 2026
4f0c24a
Merge pull request #152 from SuperToolMake/feature/v3-rest-query
mohagan9 Aug 7, 2026
885ec1e
Merge branch 'main' into feature/v3
mohagan9 Aug 9, 2026
45c5360
Merge branch 'main' into feature/v3
mohagan9 Aug 10, 2026
6fd2c01
Merge branch 'main' into feature/v3
mohagan9 Aug 12, 2026
e57809b
lint
mohagan9 Aug 12, 2026
7dae23c
Merge branch 'main' into feature/v3
mohagan9 Aug 14, 2026
f752b70
Fix build
mohagan9 Aug 14, 2026
3cde444
Bug fixes
mohagan9 Aug 14, 2026
a7decc9
Merge branch 'main' into feature/v3
mohagan9 Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion packages/backend-core/src/utils/outboundFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,9 @@ export async function fetchWithBlacklist<
nextRequest = nextRequestForRedirect(nextRequest, response.status)
if (shouldStripSensitiveHeadersForRedirect(nextUrl, redirectUrl)) {
if (rejectCrossOriginRedirects) {
throw new Error("Redirect to a different origin is not permitted.")
throw new Error(
"This API URL redirects to a different hostname, port, or protocol. Enter the final URL directly (www.example.com instead of example.com)."
)
}
nextRequest = stripSensitiveHeadersForRedirect(nextRequest)
}
Expand Down
4 changes: 3 additions & 1 deletion packages/backend-core/src/utils/tests/outboundFetch.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,9 @@ describe("outboundFetch", () => {
fetchWithBlacklist("https://budibase.com/resource", undefined, {
rejectCrossOriginRedirects: true,
})
).rejects.toThrow("Redirect to a different origin is not permitted.")
).rejects.toThrow(
"This API URL redirects to a different hostname, port, or protocol. Enter the final URL directly (www.example.com instead of example.com)."
)
expect(fetchMock).toHaveBeenCalledTimes(1)
})

Expand Down
1 change: 1 addition & 0 deletions packages/builder/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"@testing-library/jest-dom": "6.4.2",
"@testing-library/svelte": "5.2.8",
"identity-obj-proxy": "3.0.0",
"jsdom": "^21.1.1",
"resize-observer-polyfill": "1.5.1",
"svelte-jester": "1.3.2",
"vite": "8.0.16",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ $isActive

export let datasource
export let query
export let indentLevel = 1

const favourites = workspaceFavouriteStore.lookup

Expand Down Expand Up @@ -94,7 +95,7 @@ $: goto = $gotoStore

<NavItem
on:contextmenu={openContextMenu}
indentLevel={1}
{indentLevel}
{icon}
iconText={iconVerb}
{iconColor}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<script>
import { Layout } from "@supertoolmake/bbui"
import { datasources, queries } from "@/stores/builder"
import { WORKSPACE_API_CONFIG_ID } from "@supertoolmake/types"
import QueryNavItem from "./QueryNavItem.svelte"

export let searchTerm

const datasource = {
_id: WORKSPACE_API_CONFIG_ID,
source: "REST",
name: "APIs",
}

$: restDatasourceIds = new Set(
($datasources.list || []).filter((source) => source.source === "REST").map((source) => source._id)
)
$: restQueries = $queries.list.filter(
(query) =>
query.datasourceId === WORKSPACE_API_CONFIG_ID || restDatasourceIds.has(query.datasourceId)
)
$: filteredQueries = restQueries.filter(
(query) => !searchTerm || query.name?.toLowerCase().includes(searchTerm.toLowerCase())
)
</script>

<div class="queries">
{#each filteredQueries as query}
<QueryNavItem {datasource} {query} indentLevel={0} />
{/each}
</div>

{#if searchTerm && filteredQueries.length === 0}
<Layout paddingY="none" paddingX="L">
<div class="no-results">There aren't any APIs matching that name</div>
</Layout>
{/if}

<style>
.queries {
display: flex;
flex-direction: column;
}

.no-results {
color: var(--spectrum-global-color-gray-600);
}
</style>
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { goto, isActive } from "@roxi/routify"
import { getContext } from "svelte"
import { API } from "@/api"
import { IntegrationTypes } from "@/constants/backend"
import { WORKSPACE_API_CONFIG_ID } from "@supertoolmake/types"
import { bb } from "@/stores/bb"
import {
appStore,
Expand Down Expand Up @@ -87,7 +88,8 @@ const queryCommands = (queries) => {
)
return queries.map((query) => {
const datasource = datasourceLookup.get(query.datasourceId)
const isRest = datasource?.source === IntegrationTypes.REST
const isRest =
datasource?.source === IntegrationTypes.REST || query.datasourceId === WORKSPACE_API_CONFIG_ID
return {
type: "Query",
name: query.name,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const EditorModes = {
const dispatch = createEventDispatcher()
let textarea
let editor
let container

// Keep editor up to date with value
// Creates an instance of a code mirror editor
Expand Down Expand Up @@ -113,10 +114,14 @@ $: editor?.setOption("mode", mode)

onMount(() => {
// Create the editor with initial value
createEditor(mode, value)
const resizeObserver = new ResizeObserver(() => editor?.refresh())
resizeObserver.observe(container)

createEditor(mode, value).then(() => editor?.refresh())

// Clean up editor on unmount
return () => {
resizeObserver.disconnect()
if (editor) {
editor.toTextArea()
}
Expand All @@ -130,6 +135,7 @@ $: editor?.setOption("mode", mode)
</div>
{/if}
<div
bind:this={container}
style={`--code-mirror-height: ${height}px; --code-mirror-resize: ${resize}`}
>
<textarea tabindex="0" bind:this={textarea} readonly {value}></textarea>
Expand Down
20 changes: 19 additions & 1 deletion packages/builder/src/components/design/Panel.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ export let showCloseButton: boolean | undefined = false
export let onClickAddButton: () => void = () => {}
export let onClickBackButton: () => void = () => {}
export let onClickCloseButton: () => void = () => {}
export let onClickHeader: () => void = () => {}
export let headerClickable: boolean | undefined = false
export let borderLeft: boolean | undefined = false
export let borderRight: boolean | undefined = false
export let borderBottomHeader: boolean | undefined = true
Expand All @@ -30,6 +32,11 @@ $: panelStyle =
: resizable
? `flex: 1 1 auto; min-width: 260px;`
: undefined

const handleCloseButtonClick = (event: MouseEvent) => {
event.stopPropagation()
onClickCloseButton()
}
</script>

<!-- svelte-ignore a11y-click-events-have-key-events -->
Expand All @@ -43,11 +50,14 @@ $: panelStyle =
style={panelStyle}
>
{#if title || customTitleContent}
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="header"
class:custom={customHeaderContent}
class:borderBottom={borderBottomHeader}
class:noHeaderBorder
class:clickable={headerClickable}
on:click={headerClickable ? onClickHeader : undefined}
>
{#if showBackButton}
<Icon name="arrow-left" hoverable on:click={onClickBackButton} />
Expand Down Expand Up @@ -81,7 +91,11 @@ $: panelStyle =
</div>
{/if}
{#if showCloseButton}
<Icon name={closeButtonIcon} hoverable on:click={onClickCloseButton} />
<Icon
name={closeButtonIcon}
hoverable
on:click={handleCloseButtonClick}
/>
{/if}
</div>
{/if}
Expand Down Expand Up @@ -188,6 +202,10 @@ $: panelStyle =
.header.custom {
border: none;
}

.header.clickable {
cursor: pointer;
}
.custom-content-wrap {
border-bottom: var(--border-light);
}
Expand Down
64 changes: 46 additions & 18 deletions packages/builder/src/components/integration/ExtraQueryConfig.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,49 @@ $: extraFields = Object.keys(config).map((key) => ({
$: extraQueryFields = query.fields.extra || {}
</script>

{#each extraFields as { key, displayName, type }}
<Label>{displayName}</Label>
{#if type === "string"}
<Input
on:change={() => populateExtraQuery(extraQueryFields)}
bind:value={extraQueryFields[key]}
/>
{/if}

{#if type === "list"}
<Select
on:change={() => populateExtraQuery(extraQueryFields)}
bind:value={extraQueryFields[key]}
options={config[key].data[query.queryVerb]}
getOptionLabel={current => current}
/>
{/if}
{/each}
<div class="extra-fields">
{#each extraFields as { key, displayName, type }}
<div class="extra-field">
<Label>{displayName}</Label>
{#if type === "string"}
<Input
on:change={() => populateExtraQuery(extraQueryFields)}
bind:value={extraQueryFields[key]}
/>
{/if}

{#if type === "list"}
<Select
on:change={() => populateExtraQuery(extraQueryFields)}
bind:value={extraQueryFields[key]}
options={config[key].data[query.queryVerb]}
getOptionLabel={current => current}
/>
{/if}
</div>
{/each}
</div>

<style>
.extra-fields {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: var(--spacing-l);
}

.extra-field {
display: flex;
flex-direction: column;
gap: var(--spacing-xs);
}

.extra-field :global(.spectrum-Form-item) {
width: 100%;
}

@media (max-width: 700px) {
.extra-fields {
grid-template-columns: 1fr;
}
}
</style>
Loading
Loading