Merge branch 'feature/query-variables' of github.com:Budibase/budibase into rest-pagination
This commit is contained in:
commit
aa56269ccb
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/auth",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"description": "Authentication middlewares for budibase builder and apps",
|
||||
"main": "src/index.js",
|
||||
"author": "Budibase",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/bbui",
|
||||
"description": "A UI solution used in the different Budibase projects.",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"license": "MPL-2.0",
|
||||
"svelte": "src/index.js",
|
||||
"module": "dist/bbui.es.js",
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
<script>
|
||||
export let value
|
||||
</script>
|
||||
|
||||
<div class="bold">{value}</div>
|
||||
|
||||
<style>
|
||||
.bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,5 @@
|
|||
<script>
|
||||
export let value
|
||||
</script>
|
||||
|
||||
<code>{value}</code>
|
|
@ -61,6 +61,10 @@ export { default as ColorPicker } from "./ColorPicker/ColorPicker.svelte"
|
|||
export { default as InlineAlert } from "./InlineAlert/InlineAlert.svelte"
|
||||
export { default as Banner } from "./Banner/Banner.svelte"
|
||||
|
||||
// Renderers
|
||||
export { default as BoldRenderer } from "./Table/BoldRenderer.svelte"
|
||||
export { default as CodeRenderer } from "./Table/CodeRenderer.svelte"
|
||||
|
||||
// Typography
|
||||
export { default as Body } from "./Typography/Body.svelte"
|
||||
export { default as Heading } from "./Typography/Heading.svelte"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/builder",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"license": "GPL-3.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
|
@ -65,10 +65,10 @@
|
|||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/bbui": "^1.0.27-alpha.1",
|
||||
"@budibase/client": "^1.0.27-alpha.1",
|
||||
"@budibase/bbui": "^1.0.27-alpha.2",
|
||||
"@budibase/client": "^1.0.27-alpha.2",
|
||||
"@budibase/colorpicker": "1.1.2",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.1",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.2",
|
||||
"@sentry/browser": "5.19.1",
|
||||
"@spectrum-css/page": "^3.0.1",
|
||||
"@spectrum-css/vars": "^3.0.1",
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
import ErrorsBox from "components/common/ErrorsBox.svelte"
|
||||
import { roles } from "stores/backend"
|
||||
|
||||
const BASE_ROLE = { _id: "", inherits: "BASIC", permissionId: "Read/Write" }
|
||||
const BASE_ROLE = { _id: "", inherits: "BASIC", permissionId: "write" }
|
||||
|
||||
let basePermissions = []
|
||||
let selectedRole = BASE_ROLE
|
||||
|
|
|
@ -175,15 +175,19 @@
|
|||
onConfirm={datasources.removeSchemaError}
|
||||
/>
|
||||
{/if}
|
||||
<Table
|
||||
on:click={({ detail }) => onClickTable(detail)}
|
||||
schema={tableSchema}
|
||||
data={Object.values(plusTables)}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
customRenderers={[{ column: "primary", component: ArrayRenderer }]}
|
||||
/>
|
||||
{#if plusTables && Object.values(plusTables).length > 0}
|
||||
<Table
|
||||
on:click={({ detail }) => onClickTable(detail)}
|
||||
schema={tableSchema}
|
||||
data={Object.values(plusTables)}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
customRenderers={[{ column: "primary", component: ArrayRenderer }]}
|
||||
/>
|
||||
{:else}
|
||||
<Body size="S"><i>No tables found.</i></Body>
|
||||
{/if}
|
||||
{#if plusTables?.length !== 0}
|
||||
<Divider size="S" />
|
||||
<div class="query-header">
|
||||
|
@ -196,14 +200,18 @@
|
|||
Tell budibase how your tables are related to get even more smart features.
|
||||
</Body>
|
||||
{/if}
|
||||
<Table
|
||||
on:click={({ detail }) => openRelationshipModal(detail.from, detail.to)}
|
||||
schema={relationshipSchema}
|
||||
data={relationshipInfo}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
/>
|
||||
{#if relationshipInfo && relationshipInfo.length > 0}
|
||||
<Table
|
||||
on:click={({ detail }) => openRelationshipModal(detail.from, detail.to)}
|
||||
schema={relationshipSchema}
|
||||
data={relationshipInfo}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
/>
|
||||
{:else}
|
||||
<Body size="S"><i>No relationships configured.</i></Body>
|
||||
{/if}
|
||||
|
||||
<style>
|
||||
.query-header {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<script>
|
||||
import { Body, Table } from "@budibase/bbui"
|
||||
import { Body, Table, BoldRenderer, CodeRenderer } from "@budibase/bbui"
|
||||
import { queries as queriesStore } from "stores/backend"
|
||||
import { goto } from "@roxi/routify"
|
||||
|
||||
|
@ -12,8 +12,8 @@
|
|||
|
||||
const dynamicVariableSchema = {
|
||||
name: "",
|
||||
value: "",
|
||||
query: "",
|
||||
value: "",
|
||||
}
|
||||
|
||||
const onClick = dynamicVariable => {
|
||||
|
@ -36,12 +36,19 @@
|
|||
}
|
||||
</script>
|
||||
|
||||
<Table
|
||||
on:click={({ detail }) => onClick(detail)}
|
||||
schema={dynamicVariableSchema}
|
||||
data={dynamicVariables}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
/>
|
||||
<Body size="S" />
|
||||
{#if dynamicVariables && dynamicVariables.length > 0}
|
||||
<Table
|
||||
on:click={({ detail }) => onClick(detail)}
|
||||
schema={dynamicVariableSchema}
|
||||
data={dynamicVariables}
|
||||
allowEditColumns={false}
|
||||
allowEditRows={false}
|
||||
allowSelectRows={false}
|
||||
customRenderers={[
|
||||
{ column: "name", component: BoldRenderer },
|
||||
{ column: "value", component: CodeRenderer },
|
||||
]}
|
||||
/>
|
||||
{:else}
|
||||
<Body size="S"><i>No dynamic variables specified.</i></Body>
|
||||
{/if}
|
||||
|
|
|
@ -120,62 +120,6 @@ export function flipHeaderState(headersActivity) {
|
|||
return enabled
|
||||
}
|
||||
|
||||
// convert dynamic variables list to simple key/val object
|
||||
export function getDynamicVariables(datasource, queryId) {
|
||||
const variablesList = datasource?.config?.dynamicVariables
|
||||
if (variablesList && variablesList.length > 0) {
|
||||
const filtered = queryId
|
||||
? variablesList.filter(variable => variable.queryId === queryId)
|
||||
: variablesList
|
||||
return filtered.reduce(
|
||||
(acc, next) => ({ ...acc, [next.name]: next.value }),
|
||||
{}
|
||||
)
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
// convert dynamic variables object back to a list, enrich with query id
|
||||
export function rebuildVariables(datasource, queryId, variables) {
|
||||
let newVariables = []
|
||||
if (variables) {
|
||||
newVariables = Object.entries(variables).map(entry => {
|
||||
return {
|
||||
name: entry[0],
|
||||
value: entry[1],
|
||||
queryId,
|
||||
}
|
||||
})
|
||||
}
|
||||
let existing = datasource?.config?.dynamicVariables || []
|
||||
// filter out any by same name
|
||||
existing = existing.filter(
|
||||
variable =>
|
||||
!newVariables.find(
|
||||
newVar => newVar.name.toLowerCase() === variable.name.toLowerCase()
|
||||
)
|
||||
)
|
||||
return [...existing, ...newVariables]
|
||||
}
|
||||
|
||||
export function shouldShowVariables(dynamicVariables, variablesReadOnly) {
|
||||
return !!(
|
||||
dynamicVariables &&
|
||||
// show when editable or when read only and not empty
|
||||
(!variablesReadOnly || Object.keys(dynamicVariables).length > 0)
|
||||
)
|
||||
}
|
||||
|
||||
export function buildAuthConfigs(datasource) {
|
||||
if (datasource?.config?.authConfigs) {
|
||||
return datasource.config.authConfigs.map(c => ({
|
||||
label: c.name,
|
||||
value: c._id,
|
||||
}))
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
export default {
|
||||
breakQueryString,
|
||||
buildQueryString,
|
||||
|
@ -184,8 +128,4 @@ export default {
|
|||
keyValueToQueryParameters,
|
||||
queryParametersToKeyValue,
|
||||
schemaToFields,
|
||||
getDynamicVariables,
|
||||
rebuildVariables,
|
||||
shouldShowVariables,
|
||||
buildAuthConfigs,
|
||||
}
|
||||
|
|
|
@ -16,17 +16,33 @@
|
|||
export let query
|
||||
export let bodyType
|
||||
|
||||
let text = ""
|
||||
let json = ""
|
||||
|
||||
$: checkRequestBody(bodyType)
|
||||
$: updateRequestBody(bodyType, text, json)
|
||||
|
||||
function checkRequestBody(type) {
|
||||
if (!bodyType || !query) {
|
||||
return
|
||||
}
|
||||
const currentType = typeof query?.fields.requestBody
|
||||
if (objectTypes.includes(type) && currentType !== "object") {
|
||||
query.fields.requestBody = {}
|
||||
} else if (textTypes.includes(type) && currentType !== "string") {
|
||||
query.fields.requestBody = ""
|
||||
const isObject = objectTypes.includes(type)
|
||||
const isText = textTypes.includes(type)
|
||||
if (isText && currentType === "string") {
|
||||
text = query.fields.requestBody
|
||||
} else if (isObject && currentType === "object") {
|
||||
json = query.fields.requestBody
|
||||
}
|
||||
}
|
||||
|
||||
function updateRequestBody(type, text, json) {
|
||||
if (type === RawRestBodyTypes.NONE) {
|
||||
query.fields.requestBody = null
|
||||
} else if (objectTypes.includes(type)) {
|
||||
query.fields.requestBody = json
|
||||
} else {
|
||||
query.fields.requestBody = text
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -49,16 +65,12 @@
|
|||
<Body size="S" weight="800">THE REQUEST DOES NOT HAVE A BODY</Body>
|
||||
</div>
|
||||
{:else if objectTypes.includes(bodyType)}
|
||||
<KeyValueBuilder
|
||||
bind:object={query.fields.requestBody}
|
||||
name="param"
|
||||
headings
|
||||
/>
|
||||
<KeyValueBuilder bind:object={json} name="param" headings />
|
||||
{:else if textTypes.includes(bodyType)}
|
||||
<CodeMirrorEditor
|
||||
height={200}
|
||||
mode={editorMode(bodyType)}
|
||||
value={query.fields.requestBody}
|
||||
value={text}
|
||||
resize="vertical"
|
||||
on:change={e => (query.fields.requestBody = e.detail)}
|
||||
/>
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
import DynamicVariableModal from "../../_components/DynamicVariableModal.svelte"
|
||||
import Placeholder from "assets/bb-spaceship.svg"
|
||||
import { cloneDeep } from "lodash/fp"
|
||||
import { RawRestBodyTypes } from "constants/backend"
|
||||
|
||||
let query, datasource
|
||||
let breakQs = {},
|
||||
|
@ -54,13 +55,10 @@
|
|||
$: checkQueryName(url)
|
||||
$: responseSuccess = response?.info?.code >= 200 && response?.info?.code < 400
|
||||
$: isGet = query?.queryVerb === "read"
|
||||
$: authConfigs = restUtils.buildAuthConfigs(datasource)
|
||||
$: authConfigs = buildAuthConfigs(datasource)
|
||||
$: schemaReadOnly = !responseSuccess
|
||||
$: variablesReadOnly = !responseSuccess
|
||||
$: showVariablesTab = restUtils.shouldShowVariables(
|
||||
dynamicVariables,
|
||||
variablesReadOnly
|
||||
)
|
||||
$: showVariablesTab = shouldShowVariables(dynamicVariables, variablesReadOnly)
|
||||
|
||||
function getSelectedQuery() {
|
||||
return cloneDeep(
|
||||
|
@ -117,11 +115,7 @@
|
|||
notifications.success(`Request saved successfully.`)
|
||||
|
||||
if (dynamicVariables) {
|
||||
datasource.config.dynamicVariables = restUtils.rebuildVariables(
|
||||
datasource,
|
||||
saveId,
|
||||
dynamicVariables
|
||||
)
|
||||
datasource.config.dynamicVariables = rebuildVariables(saveId)
|
||||
datasource = await datasources.save(datasource)
|
||||
}
|
||||
} catch (err) {
|
||||
|
@ -160,6 +154,16 @@
|
|||
return id
|
||||
}
|
||||
|
||||
const buildAuthConfigs = datasource => {
|
||||
if (datasource?.config?.authConfigs) {
|
||||
return datasource.config.authConfigs.map(c => ({
|
||||
label: c.name,
|
||||
value: c._id,
|
||||
}))
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
const schemaMenuItems = [
|
||||
{
|
||||
text: "Create dynamic variable",
|
||||
|
@ -179,6 +183,49 @@
|
|||
},
|
||||
]
|
||||
|
||||
// convert dynamic variables list to simple key/val object
|
||||
const getDynamicVariables = (datasource, queryId) => {
|
||||
const variablesList = datasource?.config?.dynamicVariables
|
||||
if (variablesList && variablesList.length > 0) {
|
||||
const filtered = queryId
|
||||
? variablesList.filter(variable => variable.queryId === queryId)
|
||||
: variablesList
|
||||
return filtered.reduce(
|
||||
(acc, next) => ({ ...acc, [next.name]: next.value }),
|
||||
{}
|
||||
)
|
||||
}
|
||||
return {}
|
||||
}
|
||||
|
||||
// convert dynamic variables object back to a list, enrich with query id
|
||||
const rebuildVariables = queryId => {
|
||||
let variables = []
|
||||
if (dynamicVariables) {
|
||||
variables = Object.entries(dynamicVariables).map(entry => {
|
||||
return {
|
||||
name: entry[0],
|
||||
value: entry[1],
|
||||
queryId,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
let existing = datasource?.config?.dynamicVariables || []
|
||||
// remove existing query variables (for changes and deletions)
|
||||
existing = existing.filter(variable => variable.queryId !== queryId)
|
||||
// re-add the new query variables
|
||||
return [...existing, ...variables]
|
||||
}
|
||||
|
||||
const shouldShowVariables = (dynamicVariables, variablesReadOnly) => {
|
||||
return !!(
|
||||
dynamicVariables &&
|
||||
// show when editable or when read only and not empty
|
||||
(!variablesReadOnly || Object.keys(dynamicVariables).length > 0)
|
||||
)
|
||||
}
|
||||
|
||||
onMount(async () => {
|
||||
query = getSelectedQuery()
|
||||
// clear any unsaved changes to the datasource
|
||||
|
@ -214,12 +261,16 @@
|
|||
}
|
||||
}
|
||||
if (query && !query.fields.bodyType) {
|
||||
query.fields.bodyType = "none"
|
||||
if (query.fields.requestBody) {
|
||||
query.fields.bodyType = RawRestBodyTypes.JSON
|
||||
} else {
|
||||
query.fields.bodyType = RawRestBodyTypes.NONE
|
||||
}
|
||||
}
|
||||
if (query && !query.fields.pagination) {
|
||||
query.fields.pagination = {}
|
||||
}
|
||||
dynamicVariables = restUtils.getDynamicVariables(datasource, query._id)
|
||||
dynamicVariables = getDynamicVariables(datasource, query._id)
|
||||
})
|
||||
</script>
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/cli",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||
"main": "src/index.js",
|
||||
"bin": {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/client",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"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": "^1.0.27-alpha.1",
|
||||
"@budibase/bbui": "^1.0.27-alpha.2",
|
||||
"@budibase/standard-components": "^0.9.139",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.1",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.2",
|
||||
"regexparam": "^1.3.0",
|
||||
"shortid": "^2.2.15",
|
||||
"svelte-spa-router": "^3.0.5"
|
||||
|
|
|
@ -57,6 +57,12 @@ module FetchMock {
|
|||
],
|
||||
bookmark: "test",
|
||||
})
|
||||
} else if (url.includes("google.com")) {
|
||||
return json({
|
||||
url,
|
||||
opts,
|
||||
value: "<!doctype html><html itemscope=\"\" itemtype=\"http://schema.org/WebPage\" lang=\"en-GB\"></html>",
|
||||
})
|
||||
}
|
||||
return fetch(url, opts)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/server",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"description": "Budibase Web Server",
|
||||
"main": "src/index.ts",
|
||||
"repository": {
|
||||
|
@ -70,9 +70,9 @@
|
|||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@apidevtools/swagger-parser": "^10.0.3",
|
||||
"@budibase/auth": "^1.0.27-alpha.1",
|
||||
"@budibase/client": "^1.0.27-alpha.1",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.1",
|
||||
"@budibase/auth": "^1.0.27-alpha.2",
|
||||
"@budibase/client": "^1.0.27-alpha.2",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.2",
|
||||
"@bull-board/api": "^3.7.0",
|
||||
"@bull-board/koa": "^3.7.0",
|
||||
"@elastic/elasticsearch": "7.10.0",
|
||||
|
|
|
@ -17,8 +17,12 @@ const parseBody = (curl: any) => {
|
|||
if (curl.data) {
|
||||
const keys = Object.keys(curl.data)
|
||||
if (keys.length) {
|
||||
const key = keys[0]
|
||||
let key = keys[0]
|
||||
try {
|
||||
// filter out the dollar syntax used by curl for shell support
|
||||
if (key.startsWith("$")) {
|
||||
key = key.substring(1)
|
||||
}
|
||||
return JSON.parse(key)
|
||||
} catch (e) {
|
||||
// do nothing
|
||||
|
|
|
@ -144,8 +144,8 @@ async function execute(ctx, opts = { rowsOnly: false }) {
|
|||
datasource,
|
||||
queryVerb: query.queryVerb,
|
||||
fields: query.fields,
|
||||
parameters: ctx.request.body.parameter,
|
||||
pagination: ctx.request.body.pagination,
|
||||
parameters: ctx.request.body.parameters,
|
||||
transformer: query.transformer,
|
||||
queryId: ctx.params.queryId,
|
||||
})
|
||||
|
|
|
@ -191,7 +191,8 @@ class QueryBuilder {
|
|||
}
|
||||
if (this.query.equal) {
|
||||
build(this.query.equal, (key, value) => {
|
||||
if (!value) {
|
||||
// 0 evaluates to false, which means we would return all rows if we don't check it
|
||||
if (!value && value !== 0) {
|
||||
return null
|
||||
}
|
||||
return `${key}:${builder.preprocess(value, allPreProcessingOpts)}`
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
// Mock out postgres for this
|
||||
jest.mock("pg")
|
||||
jest.mock("node-fetch")
|
||||
|
||||
// Mock isProdAppID to we can later mock the implementation and pretend we are
|
||||
// using prod app IDs
|
||||
|
@ -226,4 +227,76 @@ describe("/queries", () => {
|
|||
.expect(400)
|
||||
})
|
||||
})
|
||||
|
||||
describe("test variables", () => {
|
||||
async function restDatasource(cfg) {
|
||||
return await config.createDatasource({
|
||||
datasource: {
|
||||
...basicDatasource().datasource,
|
||||
source: "REST",
|
||||
config: cfg || {},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
it("should work with static variables", async () => {
|
||||
const datasource = await restDatasource({
|
||||
staticVariables: {
|
||||
variable: "google",
|
||||
variable2: "1",
|
||||
},
|
||||
})
|
||||
const res = await request
|
||||
.post(`/api/queries/preview`)
|
||||
.send({
|
||||
datasourceId: datasource._id,
|
||||
parameters: {},
|
||||
fields: {
|
||||
path: "www.{{ variable }}.com",
|
||||
queryString: "test={{ variable2 }}",
|
||||
},
|
||||
queryVerb: "read",
|
||||
})
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
// these responses come from the mock
|
||||
expect(res.body.schemaFields).toEqual(["url", "opts", "value"])
|
||||
expect(res.body.rows[0].url).toEqual("http://www.google.com?test=1")
|
||||
})
|
||||
|
||||
it("should work with dynamic variables", async () => {
|
||||
const datasource = await restDatasource()
|
||||
const basedOnQuery = await config.createQuery({
|
||||
...basicQuery(datasource._id),
|
||||
fields: {
|
||||
path: "www.google.com",
|
||||
},
|
||||
})
|
||||
await config.updateDatasource({
|
||||
...datasource,
|
||||
config: {
|
||||
dynamicVariables: [
|
||||
{ queryId: basedOnQuery._id, name: "variable3", value: "{{ data.0.[value] }}" }
|
||||
]
|
||||
}
|
||||
})
|
||||
const res = await request
|
||||
.post(`/api/queries/preview`)
|
||||
.send({
|
||||
datasourceId: datasource._id,
|
||||
parameters: {},
|
||||
fields: {
|
||||
path: "www.google.com",
|
||||
queryString: "test={{ variable3 }}",
|
||||
},
|
||||
queryVerb: "read",
|
||||
})
|
||||
.set(config.defaultHeaders())
|
||||
.expect("Content-Type", /json/)
|
||||
.expect(200)
|
||||
expect(res.body.schemaFields).toEqual(["url", "opts", "value"])
|
||||
expect(res.body.rows[0].url).toContain("doctype html")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
@ -242,6 +242,16 @@ export interface RestConfig {
|
|||
[key: string]: any
|
||||
}
|
||||
authConfigs: AuthConfig[]
|
||||
staticVariables: {
|
||||
[key: string]: string
|
||||
}
|
||||
dynamicVariables: [
|
||||
{
|
||||
name: string
|
||||
queryId: string
|
||||
value: string
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export interface PaginationConfig {
|
||||
|
|
|
@ -53,7 +53,10 @@ module RestModule {
|
|||
const { performance } = require("perf_hooks")
|
||||
const FormData = require("form-data")
|
||||
const { URLSearchParams } = require("url")
|
||||
const { parseStringPromise: xmlParser, Builder: XmlBuilder } = require("xml2js")
|
||||
const {
|
||||
parseStringPromise: xmlParser,
|
||||
Builder: XmlBuilder,
|
||||
} = require("xml2js")
|
||||
|
||||
const SCHEMA: Integration = {
|
||||
docs: "https://github.com/node-fetch/node-fetch",
|
||||
|
@ -238,7 +241,7 @@ module RestModule {
|
|||
break
|
||||
case BodyTypes.XML:
|
||||
if (object != null) {
|
||||
string = (new XmlBuilder()).buildObject(object)
|
||||
string = new XmlBuilder().buildObject(object)
|
||||
}
|
||||
input.body = string
|
||||
input.headers["Content-Type"] = "application/xml"
|
||||
|
|
|
@ -316,6 +316,16 @@ class TestConfiguration {
|
|||
return this.datasource
|
||||
}
|
||||
|
||||
async updateDatasource(datasource) {
|
||||
const response = await this._req(
|
||||
datasource,
|
||||
{ datasourceId: datasource._id },
|
||||
controllers.datasource.update
|
||||
)
|
||||
this.datasource = response.datasource
|
||||
return this.datasource
|
||||
}
|
||||
|
||||
async createQuery(config = null) {
|
||||
if (!this.datasource && !config) {
|
||||
throw "No data source created for query."
|
||||
|
|
|
@ -5,6 +5,9 @@ const { integrations } = require("../integrations")
|
|||
const { processStringSync } = require("@budibase/string-templates")
|
||||
const CouchDB = require("../db")
|
||||
|
||||
const IS_TRIPLE_BRACE = new RegExp(/^{{3}.*}{3}$/)
|
||||
const IS_HANDLEBARS = new RegExp(/^{{2}.*}{2}$/)
|
||||
|
||||
class QueryRunner {
|
||||
constructor(input, flags = { noRecursiveQuery: false }) {
|
||||
this.appId = input.appId
|
||||
|
@ -171,7 +174,12 @@ class QueryRunner {
|
|||
enrichedQuery[key] = this.enrichQueryFields(fields[key], parameters)
|
||||
} else if (typeof fields[key] === "string") {
|
||||
// enrich string value as normal
|
||||
enrichedQuery[key] = processStringSync(fields[key], parameters, {
|
||||
let value = fields[key]
|
||||
// add triple brace to avoid escaping e.g. '=' in cookie header
|
||||
if (IS_HANDLEBARS.test(value) && !IS_TRIPLE_BRACE.test(value)) {
|
||||
value = `{${value}}`
|
||||
}
|
||||
enrichedQuery[key] = processStringSync(value, parameters, {
|
||||
noHelpers: true,
|
||||
})
|
||||
} else {
|
||||
|
|
|
@ -3,7 +3,6 @@ const CouchDB = require("../db")
|
|||
const { init } = require("@budibase/auth")
|
||||
const redis = require("@budibase/auth/redis")
|
||||
const { SEPARATOR } = require("@budibase/auth/db")
|
||||
const { processStringSync } = require("@budibase/string-templates")
|
||||
|
||||
const VARIABLE_TTL_SECONDS = 3600
|
||||
let client
|
||||
|
|
|
@ -983,10 +983,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/auth@^1.0.27-alpha.1":
|
||||
version "1.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-1.0.33.tgz#bb0c527ebca852c001c7e163a9cdfce49984adab"
|
||||
integrity sha512-CJcBspSB6B4UwXenGfzCiBh4wWPq9ZrRZm+Dqo774Yw7dfa/hHisfFiRAuz0vHxZl6AStLUsTBNynrzt7bs7Mg==
|
||||
"@budibase/auth@^1.0.27-alpha.2":
|
||||
version "1.0.34"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/auth/-/auth-1.0.34.tgz#f1daad174d494c5baae29ebfb2d0cf7a26d487bb"
|
||||
integrity sha512-RN5xZVqk4D4GIFoTrm6kv6vxIcAyDgoopsGMYj8dQRCYWb6pvWzCKyDw4o1THXiK8BBD8ctFUE/FhtLXRj8F4w==
|
||||
dependencies:
|
||||
"@techpass/passport-openidconnect" "^0.3.0"
|
||||
aws-sdk "^2.901.0"
|
||||
|
@ -1056,10 +1056,10 @@
|
|||
svelte-flatpickr "^3.2.3"
|
||||
svelte-portal "^1.0.0"
|
||||
|
||||
"@budibase/bbui@^1.0.33":
|
||||
version "1.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.33.tgz#e815c4883dbc9d28d31900160fc74aafc81d02c1"
|
||||
integrity sha512-2W3Ub8J8brSuhwtXhznszTa54cTyUdDNMFDCnRrHseaDV05XrSykdndXYyWi4XC+FveV82AdvSICxgd6alRGzg==
|
||||
"@budibase/bbui@^1.0.34":
|
||||
version "1.0.34"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.0.34.tgz#3eba93984cd0075aecbf4ca8451b301e623c7afa"
|
||||
integrity sha512-9mVzIWx4dQ8LIy4ncJaJBVwuTx2LEMqZl1XRr/NAI3rsTv+HIULe+zCUJSCYM2MGoR3qKSU7geIzIuwnRa8k4Q==
|
||||
dependencies:
|
||||
"@adobe/spectrum-css-workflow-icons" "^1.2.1"
|
||||
"@spectrum-css/actionbutton" "^1.0.1"
|
||||
|
@ -1106,14 +1106,14 @@
|
|||
svelte-flatpickr "^3.2.3"
|
||||
svelte-portal "^1.0.0"
|
||||
|
||||
"@budibase/client@^1.0.27-alpha.1":
|
||||
version "1.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-1.0.33.tgz#715aaaf15f13d9e40960fffea44002e817d8a569"
|
||||
integrity sha512-4+xM/ZTI247JbJc1noQS58VFh8AqfuQK1ZUSZIowuol1TtDu5dLGN7BysUFUe0mJZoDB/L+cB1I//43XqaSWDw==
|
||||
"@budibase/client@^1.0.27-alpha.2":
|
||||
version "1.0.34"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/client/-/client-1.0.34.tgz#2bdac2030eabf780659481fa751cd7fecf1b609f"
|
||||
integrity sha512-WGEVjwmKYv+B+J6crbia62BNFCzgKHEggsNAlCN3+IB+w9jxS2oiOJYPpYQnsSM2l4j4/Zbu9W30OhenSiB8kQ==
|
||||
dependencies:
|
||||
"@budibase/bbui" "^1.0.33"
|
||||
"@budibase/bbui" "^1.0.34"
|
||||
"@budibase/standard-components" "^0.9.139"
|
||||
"@budibase/string-templates" "^1.0.33"
|
||||
"@budibase/string-templates" "^1.0.34"
|
||||
regexparam "^1.3.0"
|
||||
shortid "^2.2.15"
|
||||
svelte-spa-router "^3.0.5"
|
||||
|
@ -1163,10 +1163,10 @@
|
|||
svelte-apexcharts "^1.0.2"
|
||||
svelte-flatpickr "^3.1.0"
|
||||
|
||||
"@budibase/string-templates@^1.0.27-alpha.1", "@budibase/string-templates@^1.0.33":
|
||||
version "1.0.33"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.33.tgz#7c39f0821d86ca1b26e8d5e7eca4256f24b09de0"
|
||||
integrity sha512-uvDJvVtAaBcMKnVylWlzGk+CzPXH+TIKojGAfgjCqfcBsc9GlyCCBLtANe8osi9Bdr1SsKOW9Fi5u9FTToNMJw==
|
||||
"@budibase/string-templates@^1.0.27-alpha.2", "@budibase/string-templates@^1.0.34":
|
||||
version "1.0.34"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/string-templates/-/string-templates-1.0.34.tgz#7e5f80a26db5d04063c0e78cdf37af88cff772c6"
|
||||
integrity sha512-HWqXxQBXqVwBgCh3ptczVFxWOLHVUhuTShXCafRDgKAVY3d+LJzKGwiD40/oR/nUqeNtBbHgYWu8Z4gMQQYZhA==
|
||||
dependencies:
|
||||
"@budibase/handlebars-helpers" "^0.11.7"
|
||||
dayjs "^1.10.4"
|
||||
|
@ -3304,9 +3304,9 @@ aws-sdk@^2.767.0:
|
|||
xml2js "0.4.19"
|
||||
|
||||
aws-sdk@^2.901.0:
|
||||
version "2.1049.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1049.0.tgz#8146dcdf3a1ab603e50ff961169ee8abc537d48e"
|
||||
integrity sha512-+wls9iNlotMeoZepwgR0yPzXsjXzr2ijoi5ERmsPWfMTFMHkm6INndBtSkm6fpu/NZnl+7EaPPES2yhaqnhoJg==
|
||||
version "2.1046.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1046.0.tgz#9147b0fa1c86acbebd1a061e951ab5012f4499d7"
|
||||
integrity sha512-ocwHclMXdIA+NWocUyvp9Ild3/zy2vr5mHp3mTyodf0WU5lzBE8PocCVLSWhMAXLxyia83xv2y5f5AzAcetbqA==
|
||||
dependencies:
|
||||
buffer "4.9.2"
|
||||
events "1.1.1"
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@budibase/string-templates",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"description": "Handlebars wrapper for Budibase templating.",
|
||||
"main": "src/index.cjs",
|
||||
"module": "dist/bundle.mjs",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@budibase/worker",
|
||||
"email": "hi@budibase.com",
|
||||
"version": "1.0.27-alpha.1",
|
||||
"version": "1.0.27-alpha.2",
|
||||
"description": "Budibase background service",
|
||||
"main": "src/index.js",
|
||||
"repository": {
|
||||
|
@ -29,8 +29,8 @@
|
|||
"author": "Budibase",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"@budibase/auth": "^1.0.27-alpha.1",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.1",
|
||||
"@budibase/auth": "^1.0.27-alpha.2",
|
||||
"@budibase/string-templates": "^1.0.27-alpha.2",
|
||||
"@koa/router": "^8.0.0",
|
||||
"@sentry/node": "^6.0.0",
|
||||
"@techpass/passport-openidconnect": "^0.3.0",
|
||||
|
|
Loading…
Reference in New Issue