Merge branch 'master' of github.com:Budibase/budibase into feature/sql-query-aliasing
This commit is contained in:
commit
f73f78c67c
|
@ -45,6 +45,16 @@
|
|||
"no-prototype-builtins": "off",
|
||||
"local-rules/no-budibase-imports": "error"
|
||||
}
|
||||
},
|
||||
{
|
||||
"files": [
|
||||
"packages/builder/**/*",
|
||||
"packages/client/**/*",
|
||||
"packages/frontend-core/**/*"
|
||||
],
|
||||
"rules": {
|
||||
"no-console": ["error", { "allow": ["warn", "error", "debug"] } ]
|
||||
}
|
||||
}
|
||||
],
|
||||
"rules": {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"version": "2.16.0",
|
||||
"version": "2.17.3",
|
||||
"npmClient": "yarn",
|
||||
"packages": [
|
||||
"packages/*",
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 485ec16a9eed48c548a5f1239772139f3319f028
|
||||
Subproject commit cc12291732ee902dc832bc7d93cf2086ffdf0cff
|
|
@ -21,7 +21,7 @@
|
|||
"test:watch": "jest --watchAll"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/nano": "10.1.4",
|
||||
"@budibase/nano": "10.1.5",
|
||||
"@budibase/pouchdb-replication-stream": "1.2.10",
|
||||
"@budibase/shared-core": "0.0.0",
|
||||
"@budibase/types": "0.0.0",
|
||||
|
|
|
@ -23,7 +23,7 @@ const getCloudfrontSignParams = () => {
|
|||
return {
|
||||
keypairId: env.CLOUDFRONT_PUBLIC_KEY_ID!,
|
||||
privateKeyString: getPrivateKey(),
|
||||
expireTime: new Date().getTime() + 1000 * 60 * 60, // 1 hour
|
||||
expireTime: new Date().getTime() + 1000 * 60 * 60 * 24, // 1 day
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import tar from "tar-fs"
|
|||
import zlib from "zlib"
|
||||
import { promisify } from "util"
|
||||
import { join } from "path"
|
||||
import fs from "fs"
|
||||
import fs, { ReadStream } from "fs"
|
||||
import env from "../environment"
|
||||
import { budibaseTempDir } from "./utils"
|
||||
import { v4 } from "uuid"
|
||||
|
@ -184,7 +184,7 @@ export async function upload({
|
|||
export async function streamUpload(
|
||||
bucketName: string,
|
||||
filename: string,
|
||||
stream: any,
|
||||
stream: ReadStream | ReadableStream,
|
||||
extra = {}
|
||||
) {
|
||||
const objectStore = ObjectStore(bucketName)
|
||||
|
|
|
@ -364,7 +364,6 @@ const getContextBindings = (asset, componentId) => {
|
|||
* Generates a set of bindings for a given component context
|
||||
*/
|
||||
const generateComponentContextBindings = (asset, componentContext) => {
|
||||
console.log("Hello ")
|
||||
const { component, definition, contexts } = componentContext
|
||||
if (!component || !definition || !contexts?.length) {
|
||||
return []
|
||||
|
|
|
@ -158,6 +158,7 @@ export const getFrontendStore = () => {
|
|||
...INITIAL_FRONTEND_STATE.features,
|
||||
...application.features,
|
||||
},
|
||||
automations: application.automations || {},
|
||||
icon: application.icon || {},
|
||||
initialised: true,
|
||||
}))
|
||||
|
|
|
@ -21,7 +21,7 @@ export const createBuilderWebsocket = appId => {
|
|||
})
|
||||
})
|
||||
socket.on("connect_error", err => {
|
||||
console.log("Failed to connect to builder websocket:", err.message)
|
||||
console.error("Failed to connect to builder websocket:", err.message)
|
||||
})
|
||||
socket.on("disconnect", () => {
|
||||
userStore.actions.reset()
|
||||
|
|
|
@ -15,7 +15,6 @@
|
|||
Icon,
|
||||
Checkbox,
|
||||
DatePicker,
|
||||
Detail,
|
||||
} from "@budibase/bbui"
|
||||
import CreateWebhookModal from "components/automation/Shared/CreateWebhookModal.svelte"
|
||||
import { automationStore, selectedAutomation } from "builderStore"
|
||||
|
@ -33,6 +32,8 @@
|
|||
import Editor from "components/integration/QueryEditor.svelte"
|
||||
import ModalBindableInput from "components/common/bindings/ModalBindableInput.svelte"
|
||||
import CodeEditor from "components/common/CodeEditor/CodeEditor.svelte"
|
||||
import BindingPicker from "components/common/bindings/BindingPicker.svelte"
|
||||
import { BindingHelpers } from "components/common/bindings/utils"
|
||||
import {
|
||||
bindingsToCompletions,
|
||||
hbAutocomplete,
|
||||
|
@ -56,7 +57,7 @@
|
|||
let drawer
|
||||
let fillWidth = true
|
||||
let inputData
|
||||
let codeBindingOpen = false
|
||||
let insertAtPos, getCaretPosition
|
||||
$: filters = lookForFilters(schemaProperties) || []
|
||||
$: tempFilters = filters
|
||||
$: stepId = block.stepId
|
||||
|
@ -75,6 +76,10 @@
|
|||
$: isUpdateRow = stepId === ActionStepID.UPDATE_ROW
|
||||
$: codeMode =
|
||||
stepId === "EXECUTE_BASH" ? EditorModes.Handlebars : EditorModes.JS
|
||||
$: bindingsHelpers = new BindingHelpers(getCaretPosition, insertAtPos, {
|
||||
disableWrapping: true,
|
||||
})
|
||||
$: editingJs = codeMode === EditorModes.JS
|
||||
|
||||
$: stepCompletions =
|
||||
codeMode === EditorModes.Handlebars
|
||||
|
@ -157,6 +162,7 @@
|
|||
let bindings = []
|
||||
let loopBlockCount = 0
|
||||
const addBinding = (name, value, icon, idx, isLoopBlock, bindingName) => {
|
||||
if (!name) return
|
||||
const runtimeBinding = determineRuntimeBinding(name, idx, isLoopBlock)
|
||||
const categoryName = determineCategoryName(idx, isLoopBlock, bindingName)
|
||||
|
||||
|
@ -291,7 +297,6 @@
|
|||
loopBlockCount++
|
||||
continue
|
||||
}
|
||||
|
||||
Object.entries(schema).forEach(([name, value]) =>
|
||||
addBinding(name, value, icon, idx, isLoopBlock, bindingName)
|
||||
)
|
||||
|
@ -539,39 +544,51 @@
|
|||
/>
|
||||
{:else if value.customType === "code"}
|
||||
<CodeEditorModal>
|
||||
{#if codeMode == EditorModes.JS}
|
||||
<ActionButton
|
||||
on:click={() => (codeBindingOpen = !codeBindingOpen)}
|
||||
quiet
|
||||
icon={codeBindingOpen ? "ChevronDown" : "ChevronRight"}
|
||||
>
|
||||
<Detail size="S">Bindings</Detail>
|
||||
</ActionButton>
|
||||
{#if codeBindingOpen}
|
||||
<pre>{JSON.stringify(bindings, null, 2)}</pre>
|
||||
{/if}
|
||||
{/if}
|
||||
<CodeEditor
|
||||
value={inputData[key]}
|
||||
on:change={e => {
|
||||
// need to pass without the value inside
|
||||
onChange({ detail: e.detail }, key)
|
||||
inputData[key] = e.detail
|
||||
}}
|
||||
completions={stepCompletions}
|
||||
mode={codeMode}
|
||||
autocompleteEnabled={codeMode != EditorModes.JS}
|
||||
height={500}
|
||||
/>
|
||||
<div class="messaging">
|
||||
{#if codeMode == EditorModes.Handlebars}
|
||||
<Icon name="FlashOn" />
|
||||
<div class="messaging-wrap">
|
||||
<div>
|
||||
Add available bindings by typing <strong>
|
||||
}}
|
||||
</strong>
|
||||
</div>
|
||||
<div class:js-editor={editingJs}>
|
||||
<div class:js-code={editingJs} style="width: 100%">
|
||||
<CodeEditor
|
||||
value={inputData[key]}
|
||||
on:change={e => {
|
||||
// need to pass without the value inside
|
||||
onChange({ detail: e.detail }, key)
|
||||
inputData[key] = e.detail
|
||||
}}
|
||||
completions={stepCompletions}
|
||||
mode={codeMode}
|
||||
autocompleteEnabled={codeMode !== EditorModes.JS}
|
||||
bind:getCaretPosition
|
||||
bind:insertAtPos
|
||||
height={500}
|
||||
/>
|
||||
<div class="messaging">
|
||||
{#if codeMode === EditorModes.Handlebars}
|
||||
<Icon name="FlashOn" />
|
||||
<div class="messaging-wrap">
|
||||
<div>
|
||||
Add available bindings by typing <strong>
|
||||
}}
|
||||
</strong>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
{#if editingJs}
|
||||
<div class="js-binding-picker">
|
||||
<BindingPicker
|
||||
{bindings}
|
||||
allowHelpers={false}
|
||||
addBinding={binding =>
|
||||
bindingsHelpers.onSelectBinding(
|
||||
inputData[key],
|
||||
binding,
|
||||
{
|
||||
js: true,
|
||||
dontDecode: true,
|
||||
}
|
||||
)}
|
||||
mode="javascript"
|
||||
/>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
@ -658,4 +675,20 @@
|
|||
.test :global(.drawer) {
|
||||
width: 10000px !important;
|
||||
}
|
||||
|
||||
.js-editor {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.js-code {
|
||||
flex: 7;
|
||||
}
|
||||
|
||||
.js-binding-picker {
|
||||
flex: 3;
|
||||
margin-top: calc((var(--spacing-xl) * -1) + 1px);
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
export let placeholder = null
|
||||
export let autocompleteEnabled = true
|
||||
export let autofocus = false
|
||||
export let jsBindingWrapping = true
|
||||
|
||||
// Export a function to expose caret position
|
||||
export const getCaretPosition = () => {
|
||||
|
@ -187,7 +188,7 @@
|
|||
)
|
||||
complete.push(
|
||||
EditorView.inputHandler.of((view, from, to, insert) => {
|
||||
if (insert === "$") {
|
||||
if (jsBindingWrapping && insert === "$") {
|
||||
let { text } = view.state.doc.lineAt(from)
|
||||
|
||||
const left = from ? text.substring(0, from) : ""
|
||||
|
|
|
@ -286,13 +286,14 @@ export const hbInsert = (value, from, to, text) => {
|
|||
return parsedInsert
|
||||
}
|
||||
|
||||
export function jsInsert(value, from, to, text, { helper } = {}) {
|
||||
export function jsInsert(value, from, to, text, { helper, disableWrapping }) {
|
||||
let parsedInsert = ""
|
||||
|
||||
const left = from ? value.substring(0, from) : ""
|
||||
const right = to ? value.substring(to) : ""
|
||||
|
||||
if (helper) {
|
||||
if (disableWrapping) {
|
||||
parsedInsert = text
|
||||
} else if (helper) {
|
||||
parsedInsert = `helpers.${text}()`
|
||||
} else if (!left.includes('$("') || !right.includes('")')) {
|
||||
parsedInsert = `$("${text}")`
|
||||
|
@ -312,7 +313,7 @@ export const insertBinding = (view, from, to, text, mode) => {
|
|||
} else if (mode.name == "handlebars") {
|
||||
parsedInsert = hbInsert(view.state.doc?.toString(), from, to, text)
|
||||
} else {
|
||||
console.log("Unsupported")
|
||||
console.warn("Unsupported")
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,9 @@
|
|||
hbAutocomplete,
|
||||
EditorModes,
|
||||
bindingsToCompletions,
|
||||
hbInsert,
|
||||
jsInsert,
|
||||
} from "../CodeEditor"
|
||||
import BindingPicker from "./BindingPicker.svelte"
|
||||
import { BindingHelpers } from "./utils"
|
||||
|
||||
const dispatch = createEventDispatcher()
|
||||
|
||||
|
@ -60,8 +59,10 @@
|
|||
let targetMode = null
|
||||
|
||||
$: usingJS = mode === "JavaScript"
|
||||
$: editorMode = mode == "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
||||
$: editorMode =
|
||||
mode === "JavaScript" ? EditorModes.JS : EditorModes.Handlebars
|
||||
$: bindingCompletions = bindingsToCompletions(bindings, editorMode)
|
||||
$: bindingHelpers = new BindingHelpers(getCaretPosition, insertAtPos)
|
||||
|
||||
const updateValue = val => {
|
||||
valid = isValid(readableToRuntimeBinding(bindings, val))
|
||||
|
@ -70,31 +71,13 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Adds a JS/HBS helper to the expression
|
||||
const onSelectHelper = (helper, js) => {
|
||||
const pos = getCaretPosition()
|
||||
const { start, end } = pos
|
||||
if (js) {
|
||||
let js = decodeJSBinding(jsValue)
|
||||
const insertVal = jsInsert(js, start, end, helper.text, { helper: true })
|
||||
insertAtPos({ start, end, value: insertVal })
|
||||
} else {
|
||||
const insertVal = hbInsert(hbsValue, start, end, helper.text)
|
||||
insertAtPos({ start, end, value: insertVal })
|
||||
}
|
||||
bindingHelpers.onSelectHelper(js ? jsValue : hbsValue, helper, { js })
|
||||
}
|
||||
|
||||
// Adds a data binding to the expression
|
||||
const onSelectBinding = (binding, { forceJS } = {}) => {
|
||||
const { start, end } = getCaretPosition()
|
||||
if (usingJS || forceJS) {
|
||||
let js = decodeJSBinding(jsValue)
|
||||
const insertVal = jsInsert(js, start, end, binding.readableBinding)
|
||||
insertAtPos({ start, end, value: insertVal })
|
||||
} else {
|
||||
const insertVal = hbInsert(hbsValue, start, end, binding.readableBinding)
|
||||
insertAtPos({ start, end, value: insertVal })
|
||||
}
|
||||
const js = usingJS || forceJS
|
||||
bindingHelpers.onSelectBinding(js ? jsValue : hbsValue, binding, { js })
|
||||
}
|
||||
|
||||
const onChangeMode = e => {
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
export let bindings
|
||||
export let mode
|
||||
export let allowHelpers
|
||||
export let noPaddingTop = false
|
||||
|
||||
let search = ""
|
||||
let popover
|
||||
|
@ -47,9 +48,10 @@
|
|||
})
|
||||
$: filteredHelpers = helpers?.filter(helper => {
|
||||
return (
|
||||
!search ||
|
||||
helper.label.match(searchRgx) ||
|
||||
helper.description.match(searchRgx)
|
||||
(!search ||
|
||||
helper.label.match(searchRgx) ||
|
||||
helper.description.match(searchRgx)) &&
|
||||
(mode.name !== "javascript" || helper.allowsJs)
|
||||
)
|
||||
})
|
||||
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
export function addHBSBinding(value, caretPos, binding) {
|
||||
binding = typeof binding === "string" ? binding : binding.path
|
||||
value = value == null ? "" : value
|
||||
import { decodeJSBinding } from "@budibase/string-templates"
|
||||
import { hbInsert, jsInsert } from "components/common/CodeEditor"
|
||||
|
||||
const left = caretPos?.start ? value.substring(0, caretPos.start) : ""
|
||||
const right = caretPos?.end ? value.substring(caretPos.end) : ""
|
||||
if (!left.includes("{{") || !right.includes("}}")) {
|
||||
binding = `{{ ${binding} }}`
|
||||
export class BindingHelpers {
|
||||
constructor(getCaretPosition, insertAtPos, { disableWrapping } = {}) {
|
||||
this.getCaretPosition = getCaretPosition
|
||||
this.insertAtPos = insertAtPos
|
||||
this.disableWrapping = disableWrapping
|
||||
}
|
||||
if (caretPos.start) {
|
||||
value =
|
||||
value.substring(0, caretPos.start) +
|
||||
binding +
|
||||
value.substring(caretPos.end, value.length)
|
||||
} else {
|
||||
value += binding
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export function addJSBinding(value, caretPos, binding, { helper } = {}) {
|
||||
binding = typeof binding === "string" ? binding : binding.path
|
||||
value = value == null ? "" : value
|
||||
if (!helper) {
|
||||
binding = `$("${binding}")`
|
||||
} else {
|
||||
binding = `helpers.${binding}()`
|
||||
// Adds a JS/HBS helper to the expression
|
||||
onSelectHelper(value, helper, { js, dontDecode }) {
|
||||
const pos = this.getCaretPosition()
|
||||
const { start, end } = pos
|
||||
if (js) {
|
||||
const jsVal = dontDecode ? value : decodeJSBinding(value)
|
||||
const insertVal = jsInsert(jsVal, start, end, helper.text, {
|
||||
helper: true,
|
||||
})
|
||||
this.insertAtPos({ start, end, value: insertVal })
|
||||
} else {
|
||||
const insertVal = hbInsert(value, start, end, helper.text)
|
||||
this.insertAtPos({ start, end, value: insertVal })
|
||||
}
|
||||
}
|
||||
if (caretPos.start) {
|
||||
value =
|
||||
value.substring(0, caretPos.start) +
|
||||
binding +
|
||||
value.substring(caretPos.end, value.length)
|
||||
} else {
|
||||
value += binding
|
||||
|
||||
// Adds a data binding to the expression
|
||||
onSelectBinding(value, binding, { js, dontDecode }) {
|
||||
const { start, end } = this.getCaretPosition()
|
||||
if (js) {
|
||||
const jsVal = dontDecode ? value : decodeJSBinding(value)
|
||||
const insertVal = jsInsert(jsVal, start, end, binding.readableBinding, {
|
||||
disableWrapping: this.disableWrapping,
|
||||
})
|
||||
this.insertAtPos({ start, end, value: insertVal })
|
||||
} else {
|
||||
const insertVal = hbInsert(value, start, end, binding.readableBinding)
|
||||
this.insertAtPos({ start, end, value: insertVal })
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@
|
|||
}))
|
||||
navigateStep(target)
|
||||
} else {
|
||||
console.log("Could not retrieve step")
|
||||
console.warn("Could not retrieve step")
|
||||
}
|
||||
} else {
|
||||
if (typeof tourStep.onComplete === "function") {
|
||||
|
|
|
@ -3,11 +3,11 @@ import { get } from "svelte/store"
|
|||
|
||||
const registerNode = async (node, tourStepKey) => {
|
||||
if (!node) {
|
||||
console.log("Tour Handler - an anchor node is required")
|
||||
console.warn("Tour Handler - an anchor node is required")
|
||||
}
|
||||
|
||||
if (!get(store).tourKey) {
|
||||
console.log("Tour Handler - No active tour ", tourStepKey, node)
|
||||
console.error("Tour Handler - No active tour ", tourStepKey, node)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -45,7 +45,7 @@ const endUserOnboarding = async ({ skipped = false } = {}) => {
|
|||
onboarding: false,
|
||||
}))
|
||||
} catch (e) {
|
||||
console.log("Onboarding failed", e)
|
||||
console.error("Onboarding failed", e)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { getManifest } from "@budibase/string-templates"
|
||||
import { getManifest, helpersToRemoveForJs } from "@budibase/string-templates"
|
||||
|
||||
export function handlebarsCompletions() {
|
||||
const manifest = getManifest()
|
||||
|
@ -11,6 +11,9 @@ export function handlebarsCompletions() {
|
|||
label: helperName,
|
||||
displayText: helperName,
|
||||
description: helperConfig.description,
|
||||
allowsJs:
|
||||
!helperConfig.requiresBlock &&
|
||||
!helpersToRemoveForJs.includes(helperName),
|
||||
}))
|
||||
)
|
||||
}
|
||||
|
|
|
@ -52,7 +52,7 @@ export const syncURLToState = options => {
|
|||
let cachedPage = get(routify.page)
|
||||
let previousParamsHash = null
|
||||
let debug = false
|
||||
const log = (...params) => debug && console.log(`[${urlParam}]`, ...params)
|
||||
const log = (...params) => debug && console.debug(`[${urlParam}]`, ...params)
|
||||
|
||||
// Navigate to a certain URL
|
||||
const gotoUrl = (url, params) => {
|
||||
|
|
|
@ -107,7 +107,7 @@
|
|||
return
|
||||
}
|
||||
if (!prodAppId) {
|
||||
console.log("Application id required")
|
||||
console.error("Application id required")
|
||||
return
|
||||
}
|
||||
await usersFetch.update({
|
||||
|
|
|
@ -66,7 +66,7 @@
|
|||
try {
|
||||
await store.actions.screens.updateSetting(get(selectedScreen), key, value)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error(error)
|
||||
notifications.error("Error saving screen settings")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@
|
|||
$goto(`./${screenId}`)
|
||||
store.actions.screens.select(screenId)
|
||||
} catch (error) {
|
||||
console.log(error)
|
||||
console.error(error)
|
||||
notifications.error("Error creating screens")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,15 +36,12 @@
|
|||
let status = null
|
||||
let timeRange = null
|
||||
let loaded = false
|
||||
|
||||
$: app = $apps.find(app => app.devId === $store.appId?.includes(app.appId))
|
||||
$: app = $apps.find(app => $store.appId?.includes(app.appId))
|
||||
$: licensePlan = $auth.user?.license?.plan
|
||||
$: page = $pageInfo.page
|
||||
$: fetchLogs(automationId, status, page, timeRange)
|
||||
$: isCloud = $admin.cloud
|
||||
|
||||
$: chainAutomations = app?.automations?.chainAutomations ?? !isCloud
|
||||
|
||||
const timeOptions = [
|
||||
{ value: "90-d", label: "Past 90 days" },
|
||||
{ value: "30-d", label: "Past 30 days" },
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
import CreateRestoreModal from "./CreateRestoreModal.svelte"
|
||||
import { createEventDispatcher } from "svelte"
|
||||
import { isOnlyUser } from "builderStore"
|
||||
import { BackupType } from "constants/backend/backups"
|
||||
|
||||
export let row
|
||||
|
||||
|
@ -42,12 +43,11 @@
|
|||
</script>
|
||||
|
||||
<div class="cell">
|
||||
<ActionMenu align="right">
|
||||
<div slot="control">
|
||||
<Icon size="M" hoverable name="MoreSmallList" />
|
||||
</div>
|
||||
|
||||
{#if row.type !== "restore"}
|
||||
{#if row.type !== BackupType.RESTORE}
|
||||
<ActionMenu align="right">
|
||||
<div slot="control">
|
||||
<Icon size="M" hoverable name="MoreSmallList" />
|
||||
</div>
|
||||
<AbsTooltip
|
||||
position={TooltipPosition.Left}
|
||||
text="Unavailable - another user is editing this app"
|
||||
|
@ -62,8 +62,8 @@
|
|||
</AbsTooltip>
|
||||
<MenuItem on:click={deleteDialog.show} icon="Delete">Delete</MenuItem>
|
||||
<MenuItem on:click={downloadExport} icon="Download">Download</MenuItem>
|
||||
{/if}
|
||||
</ActionMenu>
|
||||
</ActionMenu>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<Modal bind:this={restoreBackupModal}>
|
||||
|
|
|
@ -31,7 +31,7 @@
|
|||
async function login() {
|
||||
form.validate()
|
||||
if (Object.keys(errors).length > 0) {
|
||||
console.log("errors", errors)
|
||||
console.error("errors", errors)
|
||||
return
|
||||
}
|
||||
try {
|
||||
|
|
|
@ -6742,6 +6742,17 @@
|
|||
"key": "disabled",
|
||||
"defaultValue": false
|
||||
},
|
||||
{
|
||||
"type": "boolean",
|
||||
"label": "Read only",
|
||||
"key": "readonly",
|
||||
"defaultValue": false,
|
||||
"dependsOn": {
|
||||
"setting": "disabled",
|
||||
"value": true,
|
||||
"invert": true
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "select",
|
||||
"label": "Layout",
|
||||
|
|
|
@ -307,7 +307,7 @@
|
|||
// Reset view
|
||||
resetView()
|
||||
} catch (e) {
|
||||
console.log("There was a problem with the map", e)
|
||||
console.error("There was a problem with the map", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@
|
|||
resolve({ initialised: true })
|
||||
})
|
||||
.catch(err => {
|
||||
console.log("There was a problem scanning the image", err)
|
||||
console.error("There was a problem scanning the image", err)
|
||||
resolve({ initialised: false })
|
||||
})
|
||||
})
|
||||
|
|
|
@ -28,6 +28,7 @@ import { fetchDatasourceSchema } from "./utils/schema.js"
|
|||
import { getAPIKey } from "./utils/api.js"
|
||||
import { enrichButtonActions } from "./utils/buttonActions.js"
|
||||
import { processStringSync, makePropSafe } from "@budibase/string-templates"
|
||||
import { fetchData, LuceneUtils } from "@budibase/frontend-core"
|
||||
|
||||
export default {
|
||||
API,
|
||||
|
@ -54,6 +55,8 @@ export default {
|
|||
linkable,
|
||||
getAction,
|
||||
fetchDatasourceSchema,
|
||||
fetchData,
|
||||
LuceneUtils,
|
||||
ContextScopes,
|
||||
getAPIKey,
|
||||
enrichButtonActions,
|
||||
|
|
|
@ -14,7 +14,7 @@ const createOrgStore = () => {
|
|||
const settingsConfigDoc = await API.getTenantConfig(tenantId)
|
||||
set({ logoUrl: settingsConfigDoc.config.logoUrl })
|
||||
} catch (e) {
|
||||
console.log("Could not init org ", e)
|
||||
console.error("Could not init org ", e)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -211,29 +211,27 @@ const deleteRowHandler = async action => {
|
|||
|
||||
const triggerAutomationHandler = async action => {
|
||||
const { fields, notificationOverride, timeout } = action.parameters
|
||||
if (fields) {
|
||||
try {
|
||||
const result = await API.triggerAutomation({
|
||||
automationId: action.parameters.automationId,
|
||||
fields,
|
||||
timeout,
|
||||
})
|
||||
|
||||
// Value will exist if automation is synchronous, so return it.
|
||||
if (result.value) {
|
||||
if (!notificationOverride) {
|
||||
notificationStore.actions.success("Automation ran successfully")
|
||||
}
|
||||
return { result }
|
||||
}
|
||||
try {
|
||||
const result = await API.triggerAutomation({
|
||||
automationId: action.parameters.automationId,
|
||||
fields,
|
||||
timeout,
|
||||
})
|
||||
|
||||
// Value will exist if automation is synchronous, so return it.
|
||||
if (result.value) {
|
||||
if (!notificationOverride) {
|
||||
notificationStore.actions.success("Automation triggered")
|
||||
notificationStore.actions.success("Automation ran successfully")
|
||||
}
|
||||
} catch (error) {
|
||||
// Abort next actions
|
||||
return false
|
||||
return { result }
|
||||
}
|
||||
|
||||
if (!notificationOverride) {
|
||||
notificationStore.actions.success("Automation triggered")
|
||||
}
|
||||
} catch (error) {
|
||||
// Abort next actions
|
||||
return false
|
||||
}
|
||||
}
|
||||
const navigationHandler = action => {
|
||||
|
|
|
@ -29,7 +29,7 @@ export const createGridWebsocket = context => {
|
|||
connectToDatasource(get(datasource))
|
||||
})
|
||||
socket.on("connect_error", err => {
|
||||
console.log("Failed to connect to grid websocket:", err.message)
|
||||
console.error("Failed to connect to grid websocket:", err.message)
|
||||
})
|
||||
|
||||
// User events
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit eb9565f568cfef14b336b14eee753119acfdd43b
|
||||
Subproject commit aaf7101cd1493215155cc8f83124c70d53eb1be4
|
|
@ -1,7 +1,13 @@
|
|||
import fs from "fs"
|
||||
import { join } from "path"
|
||||
|
||||
module AwsMock {
|
||||
const aws: any = {}
|
||||
|
||||
const response = (body: any) => () => ({ promise: () => body })
|
||||
const response = (body: any, extra?: any) => () => ({
|
||||
promise: () => body,
|
||||
...extra,
|
||||
})
|
||||
|
||||
function DocumentClient() {
|
||||
// @ts-ignore
|
||||
|
@ -73,9 +79,18 @@ module AwsMock {
|
|||
|
||||
// @ts-ignore
|
||||
this.getObject = jest.fn(
|
||||
response({
|
||||
Body: "",
|
||||
})
|
||||
response(
|
||||
{
|
||||
Body: "",
|
||||
},
|
||||
{
|
||||
createReadStream: jest
|
||||
.fn()
|
||||
.mockReturnValue(
|
||||
fs.createReadStream(join(__dirname, "aws-sdk.ts"))
|
||||
),
|
||||
}
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -445,6 +445,9 @@ export async function update(ctx: UserCtx) {
|
|||
name: app.name,
|
||||
url: app.url,
|
||||
icon: app.icon,
|
||||
automations: {
|
||||
chainAutomations: app.automations?.chainAutomations,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -165,8 +165,9 @@ export async function importApp(
|
|||
const isTar = template.file && template?.file?.type?.endsWith("gzip")
|
||||
const isDirectory =
|
||||
template.file && fs.lstatSync(template.file.path).isDirectory()
|
||||
let tmpPath: string | undefined = undefined
|
||||
if (template.file && (isTar || isDirectory)) {
|
||||
const tmpPath = isTar ? await untarFile(template.file) : template.file.path
|
||||
tmpPath = isTar ? await untarFile(template.file) : template.file.path
|
||||
if (isTar && template.file.password) {
|
||||
await decryptFiles(tmpPath, template.file.password)
|
||||
}
|
||||
|
@ -208,5 +209,9 @@ export async function importApp(
|
|||
}
|
||||
await updateAttachmentColumns(prodAppId, db)
|
||||
await updateAutomations(prodAppId, db)
|
||||
// clear up afterward
|
||||
if (tmpPath) {
|
||||
fs.rmSync(tmpPath, { recursive: true, force: true })
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import fetch from "node-fetch"
|
||||
import { Response, default as fetch } from "node-fetch"
|
||||
import env from "../environment"
|
||||
import { checkSlashesInUrl } from "./index"
|
||||
import {
|
||||
|
@ -40,25 +40,21 @@ export function request(ctx?: Ctx, request?: any) {
|
|||
}
|
||||
|
||||
async function checkResponse(
|
||||
response: any,
|
||||
response: Response,
|
||||
errorMsg: string,
|
||||
{ ctx }: { ctx?: Ctx } = {}
|
||||
) {
|
||||
if (response.status !== 200) {
|
||||
let error
|
||||
try {
|
||||
error = await response.json()
|
||||
if (!error.message) {
|
||||
error = JSON.stringify(error)
|
||||
}
|
||||
} catch (err) {
|
||||
error = await response.text()
|
||||
if (response.status >= 300) {
|
||||
let responseErrorMessage
|
||||
if (response.headers.get("content-type")?.includes("json")) {
|
||||
const error = await response.json()
|
||||
responseErrorMessage = error.message ?? JSON.stringify(error)
|
||||
} else {
|
||||
responseErrorMessage = await response.text()
|
||||
}
|
||||
const msg = `Unable to ${errorMsg} - ${
|
||||
error.message ? error.message : error
|
||||
}`
|
||||
const msg = `Unable to ${errorMsg} - ${responseErrorMessage}`
|
||||
if (ctx) {
|
||||
ctx.throw(400, msg)
|
||||
ctx.throw(msg, response.status)
|
||||
} else {
|
||||
throw msg
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -25,7 +25,7 @@
|
|||
"manifest": "node ./scripts/gen-collection-info.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@budibase/handlebars-helpers": "^0.13.0",
|
||||
"@budibase/handlebars-helpers": "^0.13.1",
|
||||
"dayjs": "^1.10.8",
|
||||
"handlebars": "^4.7.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
|
|
|
@ -10,8 +10,8 @@ const marked = require("marked")
|
|||
* https://github.com/budibase/handlebars-helpers
|
||||
*/
|
||||
const { join } = require("path")
|
||||
const path = require("path")
|
||||
|
||||
const DIRECTORY = join(__dirname, "..", "..", "..")
|
||||
const COLLECTIONS = [
|
||||
"math",
|
||||
"array",
|
||||
|
@ -115,6 +115,8 @@ function getCommentInfo(file, func) {
|
|||
docs.example = docs.example.replace("product", "multiply")
|
||||
}
|
||||
docs.description = blocks[0].trim()
|
||||
docs.acceptsBlock = docs.tags.some(el => el.title === "block")
|
||||
docs.acceptsInline = docs.tags.some(el => el.title === "inline")
|
||||
return docs
|
||||
}
|
||||
|
||||
|
@ -127,7 +129,7 @@ function run() {
|
|||
const foundNames = []
|
||||
for (let collection of COLLECTIONS) {
|
||||
const collectionFile = fs.readFileSync(
|
||||
`${DIRECTORY}/node_modules/${HELPER_LIBRARY}/lib/${collection}.js`,
|
||||
`${path.dirname(require.resolve(HELPER_LIBRARY))}/lib/${collection}.js`,
|
||||
"utf8"
|
||||
)
|
||||
const collectionInfo = {}
|
||||
|
@ -159,6 +161,7 @@ function run() {
|
|||
numArgs: args.length,
|
||||
example: jsDocInfo.example || undefined,
|
||||
description: jsDocInfo.description,
|
||||
requiresBlock: jsDocInfo.acceptsBlock && !jsDocInfo.acceptsInline,
|
||||
})
|
||||
}
|
||||
outputJSON[collection] = collectionInfo
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
const { getHelperList } = require("../helpers")
|
||||
const { getJsHelperList } = require("../helpers")
|
||||
|
||||
function getLayers(fullBlock) {
|
||||
let layers = []
|
||||
|
@ -109,7 +109,7 @@ module.exports.convertHBSBlock = (block, blockNumber) => {
|
|||
const layers = getLayers(block)
|
||||
|
||||
let value = null
|
||||
const list = getHelperList()
|
||||
const list = getJsHelperList()
|
||||
for (let layer of layers) {
|
||||
const parts = splitBySpace(layer)
|
||||
if (value || parts.length > 1 || list[parts[0]]) {
|
||||
|
|
|
@ -115,7 +115,7 @@ module.exports.duration = (str, pattern, format) => {
|
|||
setLocale(config.str, config.pattern)
|
||||
|
||||
const duration = dayjs.duration(config.str, config.pattern)
|
||||
if (!isOptions(format)) {
|
||||
if (format && !isOptions(format)) {
|
||||
return duration.format(format)
|
||||
} else {
|
||||
return duration.humanize()
|
||||
|
|
|
@ -7,7 +7,7 @@ const {
|
|||
HelperFunctionBuiltin,
|
||||
LITERAL_MARKER,
|
||||
} = require("./constants")
|
||||
const { getHelperList } = require("./list")
|
||||
const { getJsHelperList } = require("./list")
|
||||
|
||||
const HTML_SWAPS = {
|
||||
"<": "<",
|
||||
|
@ -97,4 +97,4 @@ module.exports.unregisterAll = handlebars => {
|
|||
externalHandlebars.unregisterAll(handlebars)
|
||||
}
|
||||
|
||||
module.exports.getHelperList = getHelperList
|
||||
module.exports.getJsHelperList = getJsHelperList
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
const { atob } = require("../utilities")
|
||||
const cloneDeep = require("lodash.clonedeep")
|
||||
const { LITERAL_MARKER } = require("../helpers/constants")
|
||||
const { getHelperList } = require("./list")
|
||||
const { getJsHelperList } = require("./list")
|
||||
|
||||
// The method of executing JS scripts depends on the bundle being built.
|
||||
// This setter is used in the entrypoint (either index.cjs or index.mjs).
|
||||
|
@ -49,7 +49,7 @@ module.exports.processJS = (handlebars, context) => {
|
|||
// app context.
|
||||
const sandboxContext = {
|
||||
$: path => getContextValue(path, cloneDeep(context)),
|
||||
helpers: getHelperList(),
|
||||
helpers: getJsHelperList(),
|
||||
}
|
||||
|
||||
// Create a sandbox with our context and run the JS
|
||||
|
|
|
@ -3,7 +3,10 @@ const helperList = require("@budibase/handlebars-helpers")
|
|||
|
||||
let helpers = undefined
|
||||
|
||||
module.exports.getHelperList = () => {
|
||||
const helpersToRemoveForJs = ["sortBy"]
|
||||
module.exports.helpersToRemoveForJs = helpersToRemoveForJs
|
||||
|
||||
module.exports.getJsHelperList = () => {
|
||||
if (helpers) {
|
||||
return helpers
|
||||
}
|
||||
|
@ -15,12 +18,17 @@ module.exports.getHelperList = () => {
|
|||
}
|
||||
for (let collection of constructed) {
|
||||
for (let [key, func] of Object.entries(collection)) {
|
||||
helpers[key] = func
|
||||
// Handlebars injects the hbs options to the helpers by default. We are adding an empty {} as a last parameter to simulate it
|
||||
helpers[key] = (...props) => func(...props, {})
|
||||
}
|
||||
}
|
||||
for (let key of Object.keys(externalHandlebars.addedHelpers)) {
|
||||
helpers[key] = externalHandlebars.addedHelpers[key]
|
||||
}
|
||||
|
||||
for (const toRemove of helpersToRemoveForJs) {
|
||||
delete helpers[toRemove]
|
||||
}
|
||||
Object.freeze(helpers)
|
||||
return helpers
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ module.exports.findHBSBlocks = templates.findHBSBlocks
|
|||
module.exports.convertToJS = templates.convertToJS
|
||||
module.exports.setJSRunner = templates.setJSRunner
|
||||
module.exports.FIND_ANY_HBS_REGEX = templates.FIND_ANY_HBS_REGEX
|
||||
module.exports.helpersToRemoveForJs = templates.helpersToRemoveForJs
|
||||
|
||||
if (!process.env.NO_JS) {
|
||||
const { VM } = require("vm2")
|
||||
|
|
|
@ -10,6 +10,7 @@ const {
|
|||
} = require("./utilities")
|
||||
const { convertHBSBlock } = require("./conversion")
|
||||
const javascript = require("./helpers/javascript")
|
||||
const { helpersToRemoveForJs } = require("./helpers/list")
|
||||
|
||||
const hbsInstance = handlebars.create()
|
||||
registerAll(hbsInstance)
|
||||
|
@ -394,3 +395,4 @@ module.exports.convertToJS = hbs => {
|
|||
}
|
||||
|
||||
module.exports.FIND_ANY_HBS_REGEX = FIND_ANY_HBS_REGEX
|
||||
module.exports.helpersToRemoveForJs = helpersToRemoveForJs
|
||||
|
|
|
@ -21,6 +21,7 @@ export const findHBSBlocks = templates.findHBSBlocks
|
|||
export const convertToJS = templates.convertToJS
|
||||
export const setJSRunner = templates.setJSRunner
|
||||
export const FIND_ANY_HBS_REGEX = templates.FIND_ANY_HBS_REGEX
|
||||
export const helpersToRemoveForJs = templates.helpersToRemoveForJs
|
||||
|
||||
if (process && !process.env.NO_JS) {
|
||||
/**
|
||||
|
|
|
@ -16,21 +16,55 @@ jest.mock("@budibase/handlebars-helpers/lib/uuid", () => {
|
|||
})
|
||||
|
||||
const fs = require("fs")
|
||||
const { processString } = require("../src/index.cjs")
|
||||
const {
|
||||
processString,
|
||||
convertToJS,
|
||||
processStringSync,
|
||||
encodeJSBinding,
|
||||
} = require("../src/index.cjs")
|
||||
|
||||
const tk = require("timekeeper")
|
||||
const { getJsHelperList } = require("../src/helpers")
|
||||
|
||||
tk.freeze("2021-01-21T12:00:00")
|
||||
|
||||
const processJS = (js, context) => {
|
||||
return processStringSync(encodeJSBinding(js), context)
|
||||
}
|
||||
|
||||
const manifest = JSON.parse(
|
||||
fs.readFileSync(require.resolve("../manifest.json"), "utf8")
|
||||
)
|
||||
|
||||
const collections = Object.keys(manifest)
|
||||
const examples = collections.reduce((acc, collection) => {
|
||||
const functions = Object.keys(manifest[collection]).filter(
|
||||
fnc => manifest[collection][fnc].example
|
||||
)
|
||||
if (functions.length) {
|
||||
const functions = Object.entries(manifest[collection])
|
||||
.filter(([_, details]) => details.example)
|
||||
.map(([name, details]) => {
|
||||
const example = details.example
|
||||
let [hbs, js] = example.split("->").map(x => x.trim())
|
||||
if (!js) {
|
||||
// The function has no return value
|
||||
return
|
||||
}
|
||||
|
||||
// Trim 's
|
||||
js = js.replace(/^\'|\'$/g, "")
|
||||
if ((parsedExpected = tryParseJson(js))) {
|
||||
if (Array.isArray(parsedExpected)) {
|
||||
if (typeof parsedExpected[0] === "object") {
|
||||
js = JSON.stringify(parsedExpected)
|
||||
} else {
|
||||
js = parsedExpected.join(",")
|
||||
}
|
||||
}
|
||||
}
|
||||
const requiresHbsBody = details.requiresBlock
|
||||
return [name, { hbs, js, requiresHbsBody }]
|
||||
})
|
||||
.filter(x => !!x)
|
||||
|
||||
if (Object.keys(functions).length) {
|
||||
acc[collection] = functions
|
||||
}
|
||||
return acc
|
||||
|
@ -55,11 +89,7 @@ function tryParseJson(str) {
|
|||
describe("manifest", () => {
|
||||
describe("examples are valid", () => {
|
||||
describe.each(Object.keys(examples))("%s", collection => {
|
||||
it.each(examples[collection])("%s", async func => {
|
||||
const example = manifest[collection][func].example
|
||||
|
||||
let [hbs, js] = example.split("->").map(x => x.trim())
|
||||
|
||||
it.each(examples[collection])("%s", async (_, { hbs, js }) => {
|
||||
const context = {
|
||||
double: i => i * 2,
|
||||
isString: x => typeof x === "string",
|
||||
|
@ -71,23 +101,40 @@ describe("manifest", () => {
|
|||
context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"'))
|
||||
})
|
||||
|
||||
if (js === undefined) {
|
||||
// The function has no return value
|
||||
return
|
||||
let result = await processString(hbs, context)
|
||||
result = result.replace(/ /g, " ")
|
||||
expect(result).toEqual(js)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
describe("can be parsed and run as js", () => {
|
||||
const jsHelpers = getJsHelperList()
|
||||
const jsExamples = Object.keys(examples).reduce((acc, v) => {
|
||||
acc[v] = examples[v].filter(([key]) => jsHelpers[key])
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
describe.each(Object.keys(jsExamples))("%s", collection => {
|
||||
it.each(
|
||||
jsExamples[collection].filter(
|
||||
([_, { requiresHbsBody }]) => !requiresHbsBody
|
||||
)
|
||||
)("%s", async (_, { hbs, js }) => {
|
||||
const context = {
|
||||
double: i => i * 2,
|
||||
isString: x => typeof x === "string",
|
||||
}
|
||||
|
||||
let result = await processString(hbs, context)
|
||||
// Trim 's
|
||||
js = js.replace(/^\'|\'$/g, "")
|
||||
if ((parsedExpected = tryParseJson(js))) {
|
||||
if (Array.isArray(parsedExpected)) {
|
||||
if (typeof parsedExpected[0] === "object") {
|
||||
js = JSON.stringify(parsedExpected)
|
||||
} else {
|
||||
js = parsedExpected.join(",")
|
||||
}
|
||||
}
|
||||
}
|
||||
const arrays = hbs.match(/\[[^/\]]+\]/)
|
||||
arrays?.forEach((arrayString, i) => {
|
||||
hbs = hbs.replace(new RegExp(escapeRegExp(arrayString)), `array${i}`)
|
||||
context[`array${i}`] = JSON.parse(arrayString.replace(/\'/g, '"'))
|
||||
})
|
||||
|
||||
let convertedJs = convertToJS(hbs)
|
||||
|
||||
let result = processJS(convertedJs, context)
|
||||
result = result.replace(/ /g, " ")
|
||||
expect(result).toEqual(js)
|
||||
})
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
},
|
||||
"jest": {},
|
||||
"devDependencies": {
|
||||
"@budibase/nano": "10.1.4",
|
||||
"@budibase/nano": "10.1.5",
|
||||
"@types/koa": "2.13.4",
|
||||
"@types/pouchdb": "6.4.0",
|
||||
"@types/redlock": "4.0.3",
|
||||
|
|
|
@ -63,7 +63,7 @@
|
|||
"koa-useragent": "^4.1.0",
|
||||
"lodash": "4.17.21",
|
||||
"node-fetch": "2.6.7",
|
||||
"nodemailer": "6.7.2",
|
||||
"nodemailer": "6.9.9",
|
||||
"passport-google-oauth": "2.0.0",
|
||||
"passport-local": "1.0.0",
|
||||
"pouchdb": "7.3.0",
|
||||
|
|
16
yarn.lock
16
yarn.lock
|
@ -2038,10 +2038,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||
|
||||
"@budibase/handlebars-helpers@^0.13.0":
|
||||
version "0.13.0"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.0.tgz#224333d14e3900b7dacf48286af1e624a9fd62ea"
|
||||
integrity sha512-g8+sFrMNxsIDnK+MmdUICTVGr6ReUFtnPp9hJX0VZwz1pN3Ynolpk/Qbu6rEWAvoU1sEqY1mXr9uo/+kEfeGbQ==
|
||||
"@budibase/handlebars-helpers@^0.13.1":
|
||||
version "0.13.1"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.13.1.tgz#d02e73c0df8305cd675e70dc37f8427eb0842080"
|
||||
integrity sha512-v4RbXhr3igvK3i2pj5cNltu/4NMxdPIzcUt/o0RoInhesNH1VSLRdweSFr6/Y34fsCR5jHZ6vltdcz2RgrTKgw==
|
||||
dependencies:
|
||||
get-object "^0.2.0"
|
||||
get-value "^3.0.1"
|
||||
|
@ -2057,10 +2057,10 @@
|
|||
to-gfm-code-block "^0.1.1"
|
||||
uuid "^9.0.1"
|
||||
|
||||
"@budibase/nano@10.1.4":
|
||||
version "10.1.4"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/nano/-/nano-10.1.4.tgz#5c2670d0b4c12d736ddd6581c57d47c0aa45efad"
|
||||
integrity sha512-J+IVaAljGideDvJss/AUxXA1599HEIUJo5c0LLlmc1KMA3GZWZjyX+w2fxAw3qF7hqFvX+qAStQgdcD3+/GPMA==
|
||||
"@budibase/nano@10.1.5":
|
||||
version "10.1.5"
|
||||
resolved "https://registry.yarnpkg.com/@budibase/nano/-/nano-10.1.5.tgz#eeaded7bfc707ecabf8fde604425b865a90c06ec"
|
||||
integrity sha512-q1eKIsYKo+iK17zsJYd3VBl+5ufQMPpHYLec0wVsid8wnJVrTQk7RNpBlBUn/EDgXM7t8XNNHlERqHu+CxJu8Q==
|
||||
dependencies:
|
||||
"@types/tough-cookie" "^4.0.2"
|
||||
axios "^1.1.3"
|
||||
|
|
Loading…
Reference in New Issue