merge
This commit is contained in:
commit
6cddc3f8f9
|
@ -11,6 +11,7 @@ on:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- develop
|
- develop
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BRANCH: ${{ github.event.pull_request.head.ref }}
|
BRANCH: ${{ github.event.pull_request.head.ref }}
|
||||||
|
|
|
@ -14,6 +14,7 @@ on:
|
||||||
- 'yarn.lock'
|
- 'yarn.lock'
|
||||||
- 'package.json'
|
- 'package.json'
|
||||||
- 'yarn.lock'
|
- 'yarn.lock'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
||||||
|
@ -26,6 +27,11 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Fail if branch is not develop
|
||||||
|
if: github.ref != 'refs/heads/develop'
|
||||||
|
run: |
|
||||||
|
echo "Ref is not develop, you must run this job from develop."
|
||||||
|
exit 1
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -14,6 +14,7 @@ on:
|
||||||
- 'yarn.lock'
|
- 'yarn.lock'
|
||||||
- 'package.json'
|
- 'package.json'
|
||||||
- 'yarn.lock'
|
- 'yarn.lock'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
POSTHOG_TOKEN: ${{ secrets.POSTHOG_TOKEN }}
|
||||||
|
@ -27,6 +28,11 @@ jobs:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- name: Fail if branch is not master
|
||||||
|
if: github.ref != 'refs/heads/master'
|
||||||
|
run: |
|
||||||
|
echo "Ref is not master, you must run this job from master."
|
||||||
|
exit 1
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v2
|
||||||
- uses: actions/setup-node@v1
|
- uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
|
|
|
@ -32,7 +32,9 @@ jobs:
|
||||||
uses: cypress-io/github-action@v2
|
uses: cypress-io/github-action@v2
|
||||||
with:
|
with:
|
||||||
install: false
|
install: false
|
||||||
command: yarn test:e2e:ci
|
command: yarn test:e2e:ci:record
|
||||||
|
env:
|
||||||
|
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||||
|
|
||||||
# TODO: upload recordings to s3
|
# TODO: upload recordings to s3
|
||||||
# - name: Configure AWS Credentials
|
# - name: Configure AWS Credentials
|
||||||
|
|
|
@ -34,6 +34,7 @@ spec:
|
||||||
{{ else }}
|
{{ else }}
|
||||||
value: http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}
|
value: http://{{ .Release.Name }}-svc-couchdb:{{ .Values.services.couchdb.port }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
{{ if .Values.services.couchdb.enabled }}
|
||||||
- name: COUCH_DB_USER
|
- name: COUCH_DB_USER
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
@ -44,6 +45,7 @@ spec:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ template "couchdb.fullname" . }}
|
name: {{ template "couchdb.fullname" . }}
|
||||||
key: adminPassword
|
key: adminPassword
|
||||||
|
{{ end }}
|
||||||
- name: ENABLE_ANALYTICS
|
- name: ENABLE_ANALYTICS
|
||||||
value: {{ .Values.globals.enableAnalytics | quote }}
|
value: {{ .Values.globals.enableAnalytics | quote }}
|
||||||
- name: INTERNAL_API_KEY
|
- name: INTERNAL_API_KEY
|
||||||
|
@ -112,6 +114,8 @@ spec:
|
||||||
value: {{ .Values.globals.google.secret | quote }}
|
value: {{ .Values.globals.google.secret | quote }}
|
||||||
- name: AUTOMATION_MAX_ITERATIONS
|
- name: AUTOMATION_MAX_ITERATIONS
|
||||||
value: {{ .Values.globals.automationMaxIterations | quote }}
|
value: {{ .Values.globals.automationMaxIterations | quote }}
|
||||||
|
- name: EXCLUDE_QUOTAS_TENANTS
|
||||||
|
value: {{ .Values.globals.excludeQuotasTenants | quote }}
|
||||||
|
|
||||||
image: budibase/apps:{{ .Values.globals.appVersion }}
|
image: budibase/apps:{{ .Values.globals.appVersion }}
|
||||||
imagePullPolicy: Always
|
imagePullPolicy: Always
|
||||||
|
|
|
@ -29,6 +29,7 @@ spec:
|
||||||
- env:
|
- env:
|
||||||
- name: CLUSTER_PORT
|
- name: CLUSTER_PORT
|
||||||
value: {{ .Values.services.worker.port | quote }}
|
value: {{ .Values.services.worker.port | quote }}
|
||||||
|
{{ if .Values.services.couchdb.enabled }}
|
||||||
- name: COUCH_DB_USER
|
- name: COUCH_DB_USER
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
|
@ -39,6 +40,7 @@ spec:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ template "couchdb.fullname" . }}
|
name: {{ template "couchdb.fullname" . }}
|
||||||
key: adminPassword
|
key: adminPassword
|
||||||
|
{{ end }}
|
||||||
- name: COUCH_DB_URL
|
- name: COUCH_DB_URL
|
||||||
{{ if .Values.services.couchdb.url }}
|
{{ if .Values.services.couchdb.url }}
|
||||||
value: {{ .Values.services.couchdb.url }}
|
value: {{ .Values.services.couchdb.url }}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"npmClient": "yarn",
|
"npmClient": "yarn",
|
||||||
"packages": [
|
"packages": [
|
||||||
"packages/*"
|
"packages/*"
|
||||||
|
|
|
@ -47,6 +47,7 @@
|
||||||
"lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint",
|
"lint:fix": "yarn run lint:fix:prettier && yarn run lint:fix:eslint",
|
||||||
"test:e2e": "lerna run cy:test --stream",
|
"test:e2e": "lerna run cy:test --stream",
|
||||||
"test:e2e:ci": "lerna run cy:ci --stream",
|
"test:e2e:ci": "lerna run cy:ci --stream",
|
||||||
|
"test:e2e:ci:record": "lerna run cy:ci:record --stream",
|
||||||
"build:specs": "lerna run specs",
|
"build:specs": "lerna run specs",
|
||||||
"build:docker": "lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -",
|
"build:docker": "lerna run build:docker && npm run build:docker:proxy:compose && cd hosting/scripts/linux/ && ./release-to-docker-hub.sh $BUDIBASE_RELEASE_VERSION && cd -",
|
||||||
"build:docker:proxy": "docker build hosting/proxy -t proxy-service",
|
"build:docker:proxy": "docker build hosting/proxy -t proxy-service",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/backend-core",
|
"name": "@budibase/backend-core",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Budibase backend core libraries used in server and worker",
|
"description": "Budibase backend core libraries used in server and worker",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
|
|
|
@ -6,6 +6,10 @@ function isTest() {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function isDev() {
|
||||||
|
return process.env.NODE_ENV !== "production"
|
||||||
|
}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
JWT_SECRET: process.env.JWT_SECRET,
|
JWT_SECRET: process.env.JWT_SECRET,
|
||||||
COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
|
COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
|
||||||
|
@ -38,6 +42,7 @@ module.exports = {
|
||||||
process.env.GLOBAL_CLOUD_BUCKET_NAME || "prod-budi-tenant-uploads",
|
process.env.GLOBAL_CLOUD_BUCKET_NAME || "prod-budi-tenant-uploads",
|
||||||
USE_COUCH: process.env.USE_COUCH || true,
|
USE_COUCH: process.env.USE_COUCH || true,
|
||||||
isTest,
|
isTest,
|
||||||
|
isDev,
|
||||||
_set(key, value) {
|
_set(key, value) {
|
||||||
process.env[key] = value
|
process.env[key] = value
|
||||||
module.exports[key] = value
|
module.exports[key] = value
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/bbui",
|
"name": "@budibase/bbui",
|
||||||
"description": "A UI solution used in the different Budibase projects.",
|
"description": "A UI solution used in the different Budibase projects.",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"module": "dist/bbui.es.js",
|
"module": "dist/bbui.es.js",
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
],
|
],
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
"@adobe/spectrum-css-workflow-icons": "^1.2.1",
|
||||||
"@budibase/string-templates": "^1.0.130-alpha.0",
|
"@budibase/string-templates": "^1.0.142",
|
||||||
"@spectrum-css/actionbutton": "^1.0.1",
|
"@spectrum-css/actionbutton": "^1.0.1",
|
||||||
"@spectrum-css/actiongroup": "^1.0.1",
|
"@spectrum-css/actiongroup": "^1.0.1",
|
||||||
"@spectrum-css/avatar": "^3.0.2",
|
"@spectrum-css/avatar": "^3.0.2",
|
||||||
|
|
|
@ -2,17 +2,22 @@
|
||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
|
export let schema
|
||||||
|
|
||||||
// adding the 0- will turn a string like 00:00:00 into a valid ISO
|
// adding the 0- will turn a string like 00:00:00 into a valid ISO
|
||||||
// date, but will make actual ISO dates invalid
|
// date, but will make actual ISO dates invalid
|
||||||
$: time = new Date(`0-${value}`)
|
$: time = new Date(`0-${value}`)
|
||||||
$: isTime = !isNaN(time)
|
$: isTimeOnly = !isNaN(time) || schema?.timeOnly
|
||||||
|
$: isDateOnly = schema?.dateOnly
|
||||||
|
$: format = isTimeOnly
|
||||||
|
? "HH:mm:ss"
|
||||||
|
: isDateOnly
|
||||||
|
? "MMMM D YYYY"
|
||||||
|
: "MMMM D YYYY, HH:mm"
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{dayjs(isTime ? time : value).format(
|
{dayjs(isTimeOnly ? time : value).format(format)}
|
||||||
isTime ? "HH:mm:ss" : "MMMM D YYYY, HH:mm"
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/builder",
|
"name": "@budibase/builder",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -14,8 +14,10 @@
|
||||||
"cy:open": "cypress open",
|
"cy:open": "cypress open",
|
||||||
"cy:run": "cypress run",
|
"cy:run": "cypress run",
|
||||||
"cy:run:ci": "xvfb-run cypress run --headed --browser chrome",
|
"cy:run:ci": "xvfb-run cypress run --headed --browser chrome",
|
||||||
|
"cy:run:ci:record": "xvfb-run cypress run --headed --browser chrome --record",
|
||||||
"cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run",
|
"cy:test": "start-server-and-test cy:setup http://localhost:4100/builder cy:run",
|
||||||
"cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci",
|
"cy:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci",
|
||||||
|
"cy:ci:record": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:run:ci:record",
|
||||||
"cy:debug": "start-server-and-test cy:setup http://localhost:4100/builder cy:open",
|
"cy:debug": "start-server-and-test cy:setup http://localhost:4100/builder cy:open",
|
||||||
"cy:debug:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:open"
|
"cy:debug:ci": "start-server-and-test cy:setup:ci http://localhost:4100/builder cy:open"
|
||||||
},
|
},
|
||||||
|
@ -65,10 +67,10 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.130-alpha.0",
|
"@budibase/bbui": "^1.0.142",
|
||||||
"@budibase/client": "^1.0.130-alpha.0",
|
"@budibase/client": "^1.0.142",
|
||||||
"@budibase/frontend-core": "^1.0.130-alpha.0",
|
"@budibase/frontend-core": "^1.0.142",
|
||||||
"@budibase/string-templates": "^1.0.130-alpha.0",
|
"@budibase/string-templates": "^1.0.142",
|
||||||
"@sentry/browser": "5.19.1",
|
"@sentry/browser": "5.19.1",
|
||||||
"@spectrum-css/page": "^3.0.1",
|
"@spectrum-css/page": "^3.0.1",
|
||||||
"@spectrum-css/vars": "^3.0.1",
|
"@spectrum-css/vars": "^3.0.1",
|
||||||
|
|
|
@ -53,6 +53,18 @@
|
||||||
x => x.blockToLoop === block.id
|
x => x.blockToLoop === block.id
|
||||||
)
|
)
|
||||||
|
|
||||||
|
async function removeLooping() {
|
||||||
|
loopingSelected = false
|
||||||
|
let loopBlock =
|
||||||
|
$automationStore.selectedAutomation?.automation.definition.steps.find(
|
||||||
|
x => x.blockToLoop === block.id
|
||||||
|
)
|
||||||
|
automationStore.actions.deleteAutomationBlock(loopBlock)
|
||||||
|
await automationStore.actions.save(
|
||||||
|
$automationStore.selectedAutomation?.automation
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
async function deleteStep() {
|
async function deleteStep() {
|
||||||
let loopBlock =
|
let loopBlock =
|
||||||
$automationStore.selectedAutomation?.automation.definition.steps.find(
|
$automationStore.selectedAutomation?.automation.definition.steps.find(
|
||||||
|
@ -151,9 +163,7 @@
|
||||||
{#if !showLooping}
|
{#if !showLooping}
|
||||||
<div class="blockSection">
|
<div class="blockSection">
|
||||||
<div class="block-options">
|
<div class="block-options">
|
||||||
<div class="delete-padding" on:click={() => deleteStep()}>
|
<ActionButton on:click={() => removeLooping()} icon="DeleteOutline" />
|
||||||
<Icon name="DeleteOutline" />
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<Layout noPadding gap="S">
|
<Layout noPadding gap="S">
|
||||||
<AutomationBlockSetup
|
<AutomationBlockSetup
|
||||||
|
|
|
@ -182,7 +182,11 @@
|
||||||
<div class="fields">
|
<div class="fields">
|
||||||
{#each schemaProperties as [key, value]}
|
{#each schemaProperties as [key, value]}
|
||||||
<div class="block-field">
|
<div class="block-field">
|
||||||
<Label>{value.title || (key === "row" ? "Table" : key)}</Label>
|
<Label
|
||||||
|
tooltip={value.title === "Binding / Value"
|
||||||
|
? "If using the String input type, please use a comma or newline separated string"
|
||||||
|
: null}>{value.title || (key === "row" ? "Table" : key)}</Label
|
||||||
|
>
|
||||||
{#if value.type === "string" && value.enum}
|
{#if value.type === "string" && value.enum}
|
||||||
<Select
|
<Select
|
||||||
on:change={e => onChange(e, key)}
|
on:change={e => onChange(e, key)}
|
||||||
|
@ -265,6 +269,7 @@
|
||||||
value={inputData[key]}
|
value={inputData[key]}
|
||||||
on:change={e => onChange(e, key)}
|
on:change={e => onChange(e, key)}
|
||||||
{bindings}
|
{bindings}
|
||||||
|
{isTestModal}
|
||||||
/>
|
/>
|
||||||
{:else if value.customType === "webhookUrl"}
|
{:else if value.customType === "webhookUrl"}
|
||||||
<WebhookDisplay
|
<WebhookDisplay
|
||||||
|
|
|
@ -4,14 +4,15 @@
|
||||||
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
import { createEventDispatcher } from "svelte"
|
import { createEventDispatcher } from "svelte"
|
||||||
import { automationStore } from "builderStore"
|
|
||||||
import RowSelectorTypes from "./RowSelectorTypes.svelte"
|
import RowSelectorTypes from "./RowSelectorTypes.svelte"
|
||||||
|
import ModalBindableInput from "../../common/bindings/ModalBindableInput.svelte"
|
||||||
|
|
||||||
const dispatch = createEventDispatcher()
|
const dispatch = createEventDispatcher()
|
||||||
|
|
||||||
export let value
|
export let value
|
||||||
export let bindings
|
export let bindings
|
||||||
export let block
|
export let block
|
||||||
|
export let isTestModal
|
||||||
|
|
||||||
let table
|
let table
|
||||||
let schemaFields
|
let schemaFields
|
||||||
|
@ -103,35 +104,18 @@
|
||||||
{#each schemaFields as [field, schema]}
|
{#each schemaFields as [field, schema]}
|
||||||
{#if !schema.autocolumn}
|
{#if !schema.autocolumn}
|
||||||
{#if schema.type !== "attachment"}
|
{#if schema.type !== "attachment"}
|
||||||
{#if $automationStore.selectedAutomation.automation.testData}
|
{#if !rowControl}
|
||||||
{#if !rowControl}
|
<RowSelectorTypes
|
||||||
<RowSelectorTypes
|
{isTestModal}
|
||||||
{field}
|
{field}
|
||||||
{schema}
|
{schema}
|
||||||
{bindings}
|
{bindings}
|
||||||
{value}
|
{value}
|
||||||
{onChange}
|
{onChange}
|
||||||
/>
|
/>
|
||||||
{:else}
|
|
||||||
<DrawerBindableInput
|
|
||||||
placeholder={placeholders[schema.type]}
|
|
||||||
panel={AutomationBindingPanel}
|
|
||||||
value={Array.isArray(value[field])
|
|
||||||
? value[field].join(" ")
|
|
||||||
: value[field]}
|
|
||||||
on:change={e => onChange(e, field, schema.type)}
|
|
||||||
label={field}
|
|
||||||
type="string"
|
|
||||||
{bindings}
|
|
||||||
fillWidth={true}
|
|
||||||
allowJS={true}
|
|
||||||
updateOnChange={false}
|
|
||||||
/>
|
|
||||||
{/if}
|
|
||||||
{:else if !rowControl}
|
|
||||||
<RowSelectorTypes {field} {schema} {bindings} {value} {onChange} />
|
|
||||||
{:else}
|
{:else}
|
||||||
<DrawerBindableInput
|
<svelte:component
|
||||||
|
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
||||||
placeholder={placeholders[schema.type]}
|
placeholder={placeholders[schema.type]}
|
||||||
panel={AutomationBindingPanel}
|
panel={AutomationBindingPanel}
|
||||||
value={Array.isArray(value[field])
|
value={Array.isArray(value[field])
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
} from "@budibase/bbui"
|
} from "@budibase/bbui"
|
||||||
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
import LinkedRowSelector from "components/common/LinkedRowSelector.svelte"
|
||||||
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
import DrawerBindableInput from "../../common/bindings/DrawerBindableInput.svelte"
|
||||||
|
import ModalBindableInput from "../../common/bindings/ModalBindableInput.svelte"
|
||||||
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
import AutomationBindingPanel from "../../common/bindings/ServerBindingPanel.svelte"
|
||||||
|
|
||||||
export let onChange
|
export let onChange
|
||||||
|
@ -15,6 +16,7 @@
|
||||||
export let schema
|
export let schema
|
||||||
export let value
|
export let value
|
||||||
export let bindings
|
export let bindings
|
||||||
|
export let isTestModal
|
||||||
|
|
||||||
function schemaHasOptions(schema) {
|
function schemaHasOptions(schema) {
|
||||||
return !!schema.constraints?.inclusion?.length
|
return !!schema.constraints?.inclusion?.length
|
||||||
|
@ -51,7 +53,8 @@
|
||||||
{:else if schema.type === "link"}
|
{:else if schema.type === "link"}
|
||||||
<LinkedRowSelector bind:linkedRows={value[field]} {schema} />
|
<LinkedRowSelector bind:linkedRows={value[field]} {schema} />
|
||||||
{:else if schema.type === "string" || schema.type === "number"}
|
{:else if schema.type === "string" || schema.type === "number"}
|
||||||
<DrawerBindableInput
|
<svelte:component
|
||||||
|
this={isTestModal ? ModalBindableInput : DrawerBindableInput}
|
||||||
panel={AutomationBindingPanel}
|
panel={AutomationBindingPanel}
|
||||||
value={value[field]}
|
value={value[field]}
|
||||||
on:change={e => onChange(e, field)}
|
on:change={e => onChange(e, field)}
|
||||||
|
|
|
@ -20,6 +20,9 @@
|
||||||
export let readonly
|
export let readonly
|
||||||
|
|
||||||
const resolveTimeStamp = timestamp => {
|
const resolveTimeStamp = timestamp => {
|
||||||
|
if (!timestamp) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
let maskedDate = new Date(`0-${timestamp}`)
|
let maskedDate = new Date(`0-${timestamp}`)
|
||||||
if (maskedDate instanceof Date && !isNaN(maskedDate.getTime())) {
|
if (maskedDate instanceof Date && !isNaN(maskedDate.getTime())) {
|
||||||
return maskedDate
|
return maskedDate
|
||||||
|
@ -34,7 +37,7 @@
|
||||||
$: label = meta.name ? capitalise(meta.name) : ""
|
$: label = meta.name ? capitalise(meta.name) : ""
|
||||||
|
|
||||||
const timeStamp = resolveTimeStamp(value)
|
const timeStamp = resolveTimeStamp(value)
|
||||||
const isTimeStamp = !!timeStamp
|
const isTimeStamp = !!timeStamp || meta?.timeOnly
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if type === "options" && meta.constraints.inclusion.length !== 0}
|
{#if type === "options" && meta.constraints.inclusion.length !== 0}
|
||||||
|
@ -46,7 +49,12 @@
|
||||||
sort
|
sort
|
||||||
/>
|
/>
|
||||||
{:else if type === "datetime"}
|
{:else if type === "datetime"}
|
||||||
<DatePicker {label} timeOnly={isTimeStamp} bind:value />
|
<DatePicker
|
||||||
|
{label}
|
||||||
|
timeOnly={isTimeStamp}
|
||||||
|
enableTime={!meta?.dateOnly}
|
||||||
|
bind:value
|
||||||
|
/>
|
||||||
{:else if type === "attachment"}
|
{:else if type === "attachment"}
|
||||||
<Dropzone {label} bind:value />
|
<Dropzone {label} bind:value />
|
||||||
{:else if type === "boolean"}
|
{:else if type === "boolean"}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
<script>
|
<script>
|
||||||
import { ActionButton } from "@budibase/bbui"
|
|
||||||
import GoogleLogo from "assets/google-logo.png"
|
import GoogleLogo from "assets/google-logo.png"
|
||||||
import { store } from "builderStore"
|
import { store } from "builderStore"
|
||||||
import { auth } from "stores/portal"
|
import { auth } from "stores/portal"
|
||||||
|
@ -10,7 +9,7 @@
|
||||||
$: tenantId = $auth.tenantId
|
$: tenantId = $auth.tenantId
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ActionButton
|
<button
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
let ds = datasource
|
let ds = datasource
|
||||||
if (!ds) {
|
if (!ds) {
|
||||||
|
@ -22,26 +21,32 @@
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div class="inner">
|
<img src={GoogleLogo} alt="google icon" />
|
||||||
<img src={GoogleLogo} alt="google icon" />
|
<p>Sign in with Google</p>
|
||||||
<p>Sign in with Google</p>
|
</button>
|
||||||
</div>
|
|
||||||
</ActionButton>
|
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.inner {
|
button {
|
||||||
|
width: 195px;
|
||||||
|
height: 40px;
|
||||||
|
font-size: 14px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
font-weight: 500;
|
||||||
padding-top: var(--spacing-xs);
|
background: #4285f4;
|
||||||
padding-bottom: var(--spacing-xs);
|
color: #ffffff;
|
||||||
|
border: none;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
border-radius: 2px;
|
||||||
}
|
}
|
||||||
.inner img {
|
|
||||||
|
img {
|
||||||
|
border-radius: 2px;
|
||||||
width: 18px;
|
width: 18px;
|
||||||
margin: 3px 10px 3px 3px;
|
margin-right: 11px;
|
||||||
}
|
background: #ffffff;
|
||||||
.inner p {
|
padding: 10px;
|
||||||
margin: 0;
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
<script>
|
||||||
|
export let width = 100
|
||||||
|
export let height = 100
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svg
|
||||||
|
{width}
|
||||||
|
{height}
|
||||||
|
viewBox="0 0 46 46"
|
||||||
|
version="1.1"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"
|
||||||
|
>
|
||||||
|
<!-- Generator: Sketch 3.3.3 (12081) - http://www.bohemiancoding.com/sketch -->
|
||||||
|
<title>btn_google_dark_normal_ios</title>
|
||||||
|
<desc>Created with Sketch.</desc>
|
||||||
|
<defs>
|
||||||
|
<filter
|
||||||
|
x="-50%"
|
||||||
|
y="-50%"
|
||||||
|
width="200%"
|
||||||
|
height="200%"
|
||||||
|
filterUnits="objectBoundingBox"
|
||||||
|
id="filter-1"
|
||||||
|
>
|
||||||
|
<feOffset dx="0" dy="1" in="SourceAlpha" result="shadowOffsetOuter1" />
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="0.5"
|
||||||
|
in="shadowOffsetOuter1"
|
||||||
|
result="shadowBlurOuter1"
|
||||||
|
/>
|
||||||
|
<feColorMatrix
|
||||||
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.168 0"
|
||||||
|
in="shadowBlurOuter1"
|
||||||
|
type="matrix"
|
||||||
|
result="shadowMatrixOuter1"
|
||||||
|
/>
|
||||||
|
<feOffset dx="0" dy="0" in="SourceAlpha" result="shadowOffsetOuter2" />
|
||||||
|
<feGaussianBlur
|
||||||
|
stdDeviation="0.5"
|
||||||
|
in="shadowOffsetOuter2"
|
||||||
|
result="shadowBlurOuter2"
|
||||||
|
/>
|
||||||
|
<feColorMatrix
|
||||||
|
values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.084 0"
|
||||||
|
in="shadowBlurOuter2"
|
||||||
|
type="matrix"
|
||||||
|
result="shadowMatrixOuter2"
|
||||||
|
/>
|
||||||
|
<feMerge>
|
||||||
|
<feMergeNode in="shadowMatrixOuter1" />
|
||||||
|
<feMergeNode in="shadowMatrixOuter2" />
|
||||||
|
<feMergeNode in="SourceGraphic" />
|
||||||
|
</feMerge>
|
||||||
|
</filter>
|
||||||
|
<rect id="path-2" x="0" y="0" width="40" height="40" rx="2" />
|
||||||
|
<rect id="path-3" x="5" y="5" width="38" height="38" rx="1" />
|
||||||
|
</defs>
|
||||||
|
<g
|
||||||
|
id="Google-Button"
|
||||||
|
stroke="none"
|
||||||
|
stroke-width="1"
|
||||||
|
fill="none"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
sketch:type="MSPage"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id="9-PATCH"
|
||||||
|
sketch:type="MSArtboardGroup"
|
||||||
|
transform="translate(-608.000000, -219.000000)"
|
||||||
|
/>
|
||||||
|
<g
|
||||||
|
id="btn_google_dark_normal"
|
||||||
|
sketch:type="MSArtboardGroup"
|
||||||
|
transform="translate(-1.000000, -1.000000)"
|
||||||
|
>
|
||||||
|
<g
|
||||||
|
id="button"
|
||||||
|
sketch:type="MSLayerGroup"
|
||||||
|
transform="translate(4.000000, 4.000000)"
|
||||||
|
filter="url(#filter-1)"
|
||||||
|
>
|
||||||
|
<g id="button-bg">
|
||||||
|
<use
|
||||||
|
fill="#4285F4"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
xlink:href="#path-2"
|
||||||
|
/>
|
||||||
|
<use fill="none" xlink:href="#path-2" />
|
||||||
|
<use fill="none" xlink:href="#path-2" />
|
||||||
|
<use fill="none" xlink:href="#path-2" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
<g id="button-bg-copy">
|
||||||
|
<use
|
||||||
|
fill="#FFFFFF"
|
||||||
|
fill-rule="evenodd"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
xlink:href="#path-3"
|
||||||
|
/>
|
||||||
|
<use fill="none" xlink:href="#path-3" />
|
||||||
|
<use fill="none" xlink:href="#path-3" />
|
||||||
|
<use fill="none" xlink:href="#path-3" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="logo_googleg_48dp"
|
||||||
|
sketch:type="MSLayerGroup"
|
||||||
|
transform="translate(15.000000, 15.000000)"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M17.64,9.20454545 C17.64,8.56636364 17.5827273,7.95272727 17.4763636,7.36363636 L9,7.36363636 L9,10.845 L13.8436364,10.845 C13.635,11.97 13.0009091,12.9231818 12.0477273,13.5613636 L12.0477273,15.8195455 L14.9563636,15.8195455 C16.6581818,14.2527273 17.64,11.9454545 17.64,9.20454545 L17.64,9.20454545 Z"
|
||||||
|
id="Shape"
|
||||||
|
fill="#4285F4"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M9,18 C11.43,18 13.4672727,17.1940909 14.9563636,15.8195455 L12.0477273,13.5613636 C11.2418182,14.1013636 10.2109091,14.4204545 9,14.4204545 C6.65590909,14.4204545 4.67181818,12.8372727 3.96409091,10.71 L0.957272727,10.71 L0.957272727,13.0418182 C2.43818182,15.9831818 5.48181818,18 9,18 L9,18 Z"
|
||||||
|
id="Shape"
|
||||||
|
fill="#34A853"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.96409091,10.71 C3.78409091,10.17 3.68181818,9.59318182 3.68181818,9 C3.68181818,8.40681818 3.78409091,7.83 3.96409091,7.29 L3.96409091,4.95818182 L0.957272727,4.95818182 C0.347727273,6.17318182 0,7.54772727 0,9 C0,10.4522727 0.347727273,11.8268182 0.957272727,13.0418182 L3.96409091,10.71 L3.96409091,10.71 Z"
|
||||||
|
id="Shape"
|
||||||
|
fill="#FBBC05"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M9,3.57954545 C10.3213636,3.57954545 11.5077273,4.03363636 12.4404545,4.92545455 L15.0218182,2.34409091 C13.4631818,0.891818182 11.4259091,0 9,0 C5.48181818,0 2.43818182,2.01681818 0.957272727,4.95818182 L3.96409091,7.29 C4.67181818,5.16272727 6.65590909,3.57954545 9,3.57954545 L9,3.57954545 Z"
|
||||||
|
id="Shape"
|
||||||
|
fill="#EA4335"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M0,0 L18,0 L18,18 L0,18 L0,0 Z"
|
||||||
|
id="Shape"
|
||||||
|
sketch:type="MSShapeGroup"
|
||||||
|
/>
|
||||||
|
</g>
|
||||||
|
<g id="handles_square" sketch:type="MSLayerGroup" />
|
||||||
|
</g>
|
||||||
|
</g>
|
||||||
|
</svg>
|
|
@ -49,6 +49,10 @@
|
||||||
filters = [...filters, duplicate]
|
filters = [...filters, duplicate]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSchema = filter => {
|
||||||
|
return schemaFields.find(field => field.name === filter.field)
|
||||||
|
}
|
||||||
|
|
||||||
const onFieldChange = (expression, field) => {
|
const onFieldChange = (expression, field) => {
|
||||||
// Update the field type
|
// Update the field type
|
||||||
expression.type = enrichedSchemaFields.find(x => x.name === field)?.type
|
expression.type = enrichedSchemaFields.find(x => x.name === field)?.type
|
||||||
|
@ -150,7 +154,12 @@
|
||||||
bind:value={filter.value}
|
bind:value={filter.value}
|
||||||
/>
|
/>
|
||||||
{:else if filter.type === "datetime"}
|
{:else if filter.type === "datetime"}
|
||||||
<DatePicker disabled={filter.noValue} bind:value={filter.value} />
|
<DatePicker
|
||||||
|
disabled={filter.noValue}
|
||||||
|
enableTime={!getSchema(filter).dateOnly}
|
||||||
|
timeOnly={getSchema(filter).timeOnly}
|
||||||
|
bind:value={filter.value}
|
||||||
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<DrawerBindableInput disabled />
|
<DrawerBindableInput disabled />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/cli",
|
"name": "@budibase/cli",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
"description": "Budibase CLI, for developers, self hosting and migrations.",
|
||||||
"main": "src/index.js",
|
"main": "src/index.js",
|
||||||
"bin": {
|
"bin": {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/client",
|
"name": "@budibase/client",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"module": "dist/budibase-client.js",
|
"module": "dist/budibase-client.js",
|
||||||
"main": "dist/budibase-client.js",
|
"main": "dist/budibase-client.js",
|
||||||
|
@ -19,9 +19,9 @@
|
||||||
"dev:builder": "rollup -cw"
|
"dev:builder": "rollup -cw"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.130-alpha.0",
|
"@budibase/bbui": "^1.0.142",
|
||||||
"@budibase/frontend-core": "^1.0.130-alpha.0",
|
"@budibase/frontend-core": "^1.0.142",
|
||||||
"@budibase/string-templates": "^1.0.130-alpha.0",
|
"@budibase/string-templates": "^1.0.142",
|
||||||
"@spectrum-css/button": "^3.0.3",
|
"@spectrum-css/button": "^3.0.3",
|
||||||
"@spectrum-css/card": "^3.0.3",
|
"@spectrum-css/card": "^3.0.3",
|
||||||
"@spectrum-css/divider": "^1.0.3",
|
"@spectrum-css/divider": "^1.0.3",
|
||||||
|
|
|
@ -88,6 +88,10 @@
|
||||||
const schema = schemaFields.find(x => x.name === field)
|
const schema = schemaFields.find(x => x.name === field)
|
||||||
return schema?.constraints?.inclusion || []
|
return schema?.constraints?.inclusion || []
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getSchema = filter => {
|
||||||
|
return schemaFields.find(field => field.name === filter.field)
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="container" class:mobile={$context.device.mobile}>
|
<div class="container" class:mobile={$context.device.mobile}>
|
||||||
|
@ -134,7 +138,12 @@
|
||||||
bind:value={filter.value}
|
bind:value={filter.value}
|
||||||
/>
|
/>
|
||||||
{:else if filter.type === "datetime"}
|
{:else if filter.type === "datetime"}
|
||||||
<DatePicker disabled={filter.noValue} bind:value={filter.value} />
|
<DatePicker
|
||||||
|
disabled={filter.noValue}
|
||||||
|
enableTime={!getSchema(filter).dateOnly}
|
||||||
|
timeOnly={getSchema(filter).timeOnly}
|
||||||
|
bind:value={filter.value}
|
||||||
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<Input disabled />
|
<Input disabled />
|
||||||
{/if}
|
{/if}
|
||||||
|
|
|
@ -44,7 +44,6 @@
|
||||||
fieldApi = value?.fieldApi
|
fieldApi = value?.fieldApi
|
||||||
fieldSchema = value?.fieldSchema
|
fieldSchema = value?.fieldSchema
|
||||||
})
|
})
|
||||||
onDestroy(() => unsubscribe?.())
|
|
||||||
|
|
||||||
// Determine label class from position
|
// Determine label class from position
|
||||||
$: labelClass = labelPos === "above" ? "" : `spectrum-FieldLabel--${labelPos}`
|
$: labelClass = labelPos === "above" ? "" : `spectrum-FieldLabel--${labelPos}`
|
||||||
|
@ -52,6 +51,11 @@
|
||||||
const updateLabel = e => {
|
const updateLabel = e => {
|
||||||
builderStore.actions.updateProp("label", e.target.textContent)
|
builderStore.actions.updateProp("label", e.target.textContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onDestroy(() => {
|
||||||
|
fieldApi?.deregister()
|
||||||
|
unsubscribe?.()
|
||||||
|
})
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<FieldGroupFallback>
|
<FieldGroupFallback>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
if (
|
if (
|
||||||
formContext &&
|
formContext &&
|
||||||
$builderStore.inBuilder &&
|
$builderStore.inBuilder &&
|
||||||
$componentStore.selectedComponentPath?.includes($component.id)
|
$componentStore?.selectedComponentPath?.includes($component.id)
|
||||||
) {
|
) {
|
||||||
formContext.formApi.setStep(step)
|
formContext.formApi.setStep(step)
|
||||||
}
|
}
|
||||||
|
|
|
@ -329,6 +329,17 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// We don't want to actually remove the field state when deregistering, just
|
||||||
|
// remove any errors and validation
|
||||||
|
const deregister = () => {
|
||||||
|
const fieldInfo = getField(field)
|
||||||
|
fieldInfo.update(state => {
|
||||||
|
state.fieldState.validator = null
|
||||||
|
state.fieldState.error = null
|
||||||
|
return state
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Updates the disabled state of a certain field
|
// Updates the disabled state of a certain field
|
||||||
const setDisabled = fieldDisabled => {
|
const setDisabled = fieldDisabled => {
|
||||||
const fieldInfo = getField(field)
|
const fieldInfo = getField(field)
|
||||||
|
@ -348,6 +359,7 @@
|
||||||
reset,
|
reset,
|
||||||
updateValidation,
|
updateValidation,
|
||||||
setDisabled,
|
setDisabled,
|
||||||
|
deregister,
|
||||||
validate: () => {
|
validate: () => {
|
||||||
// Validate the field by force setting the same value again
|
// Validate the field by force setting the same value again
|
||||||
const { fieldState } = get(getField(field))
|
const { fieldState } = get(getField(field))
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/frontend-core",
|
"name": "@budibase/frontend-core",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Budibase frontend core libraries used in builder and client",
|
"description": "Budibase frontend core libraries used in builder and client",
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"svelte": "src/index.js",
|
"svelte": "src/index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/bbui": "^1.0.130-alpha.0",
|
"@budibase/bbui": "^1.0.142",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"svelte": "^3.46.2"
|
"svelte": "^3.46.2"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/server",
|
"name": "@budibase/server",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Budibase Web Server",
|
"description": "Budibase Web Server",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -68,10 +68,10 @@
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@apidevtools/swagger-parser": "^10.0.3",
|
"@apidevtools/swagger-parser": "^10.0.3",
|
||||||
"@budibase/backend-core": "^1.0.130-alpha.0",
|
"@budibase/backend-core": "^1.0.142",
|
||||||
"@budibase/client": "^1.0.130-alpha.0",
|
"@budibase/client": "^1.0.142",
|
||||||
"@budibase/pro": "1.0.130-alpha.0",
|
"@budibase/pro": "1.0.142",
|
||||||
"@budibase/string-templates": "^1.0.130-alpha.0",
|
"@budibase/string-templates": "^1.0.142",
|
||||||
"@bull-board/api": "^3.7.0",
|
"@bull-board/api": "^3.7.0",
|
||||||
"@bull-board/koa": "^3.7.0",
|
"@bull-board/koa": "^3.7.0",
|
||||||
"@elastic/elasticsearch": "7.10.0",
|
"@elastic/elasticsearch": "7.10.0",
|
||||||
|
|
|
@ -86,3 +86,15 @@ exports.substituteLoopStep = (hbsString, substitute) => {
|
||||||
|
|
||||||
return hbsString
|
return hbsString
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.stringSplit = value => {
|
||||||
|
if (value == null) {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
if (value.split("\n").length > 1) {
|
||||||
|
value = value.split("\n")
|
||||||
|
} else {
|
||||||
|
value = value.split(",")
|
||||||
|
}
|
||||||
|
return value
|
||||||
|
}
|
||||||
|
|
|
@ -242,12 +242,10 @@ module MSSQLModule {
|
||||||
if (typeof name !== "string") {
|
if (typeof name !== "string") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
const type: string = convertSqlType(def.DATA_TYPE)
|
|
||||||
|
|
||||||
schema[name] = {
|
schema[name] = {
|
||||||
autocolumn: !!autoColumns.find((col: string) => col === name),
|
autocolumn: !!autoColumns.find((col: string) => col === name),
|
||||||
name: name,
|
name: name,
|
||||||
type,
|
...convertSqlType(def.DATA_TYPE),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tables[tableName] = {
|
tables[tableName] = {
|
||||||
|
|
|
@ -15,6 +15,7 @@ import {
|
||||||
} from "./utils"
|
} from "./utils"
|
||||||
import { DatasourcePlus } from "./base/datasourcePlus"
|
import { DatasourcePlus } from "./base/datasourcePlus"
|
||||||
import dayjs from "dayjs"
|
import dayjs from "dayjs"
|
||||||
|
import { FieldTypes } from "../constants"
|
||||||
const { NUMBER_REGEX } = require("../utilities")
|
const { NUMBER_REGEX } = require("../utilities")
|
||||||
|
|
||||||
module MySQLModule {
|
module MySQLModule {
|
||||||
|
@ -101,7 +102,7 @@ module MySQLModule {
|
||||||
}
|
}
|
||||||
// if not a number, see if it is a date - important to do in this order as any
|
// if not a number, see if it is a date - important to do in this order as any
|
||||||
// integer will be considered a valid date
|
// integer will be considered a valid date
|
||||||
else if (dayjs(binding).isValid()) {
|
else if (/^\d/.test(binding) && dayjs(binding).isValid()) {
|
||||||
bindings[i] = dayjs(binding).toDate()
|
bindings[i] = dayjs(binding).toDate()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -151,20 +152,24 @@ module MySQLModule {
|
||||||
|
|
||||||
async internalQuery(
|
async internalQuery(
|
||||||
query: SqlQuery,
|
query: SqlQuery,
|
||||||
connect: boolean = true
|
opts: { connect?: boolean; disableCoercion?: boolean } = {
|
||||||
|
connect: true,
|
||||||
|
disableCoercion: false,
|
||||||
|
}
|
||||||
): Promise<any[] | any> {
|
): Promise<any[] | any> {
|
||||||
try {
|
try {
|
||||||
if (connect) {
|
if (opts?.connect) {
|
||||||
await this.connect()
|
await this.connect()
|
||||||
}
|
}
|
||||||
|
const baseBindings = query.bindings || []
|
||||||
|
const bindings = opts?.disableCoercion
|
||||||
|
? baseBindings
|
||||||
|
: bindingTypeCoerce(baseBindings)
|
||||||
// Node MySQL is callback based, so we must wrap our call in a promise
|
// Node MySQL is callback based, so we must wrap our call in a promise
|
||||||
const response = await this.client.query(
|
const response = await this.client.query(query.sql, bindings)
|
||||||
query.sql,
|
|
||||||
bindingTypeCoerce(query.bindings || [])
|
|
||||||
)
|
|
||||||
return response[0]
|
return response[0]
|
||||||
} finally {
|
} finally {
|
||||||
if (connect) {
|
if (opts?.connect) {
|
||||||
await this.disconnect()
|
await this.disconnect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -179,7 +184,7 @@ module MySQLModule {
|
||||||
// get the tables first
|
// get the tables first
|
||||||
const tablesResp = await this.internalQuery(
|
const tablesResp = await this.internalQuery(
|
||||||
{ sql: "SHOW TABLES;" },
|
{ sql: "SHOW TABLES;" },
|
||||||
false
|
{ connect: false }
|
||||||
)
|
)
|
||||||
const tableNames = tablesResp.map(
|
const tableNames = tablesResp.map(
|
||||||
(obj: any) =>
|
(obj: any) =>
|
||||||
|
@ -191,7 +196,7 @@ module MySQLModule {
|
||||||
const schema: TableSchema = {}
|
const schema: TableSchema = {}
|
||||||
const descResp = await this.internalQuery(
|
const descResp = await this.internalQuery(
|
||||||
{ sql: `DESCRIBE \`${tableName}\`;` },
|
{ sql: `DESCRIBE \`${tableName}\`;` },
|
||||||
false
|
{ connect: false }
|
||||||
)
|
)
|
||||||
for (let column of descResp) {
|
for (let column of descResp) {
|
||||||
const columnName = column.Field
|
const columnName = column.Field
|
||||||
|
@ -211,8 +216,8 @@ module MySQLModule {
|
||||||
schema[columnName] = {
|
schema[columnName] = {
|
||||||
name: columnName,
|
name: columnName,
|
||||||
autocolumn: isAuto,
|
autocolumn: isAuto,
|
||||||
type: convertSqlType(column.Type),
|
|
||||||
constraints,
|
constraints,
|
||||||
|
...convertSqlType(column.Type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!tables[tableName]) {
|
if (!tables[tableName]) {
|
||||||
|
@ -254,7 +259,8 @@ module MySQLModule {
|
||||||
async query(json: QueryJson) {
|
async query(json: QueryJson) {
|
||||||
await this.connect()
|
await this.connect()
|
||||||
try {
|
try {
|
||||||
const queryFn = (query: any) => this.internalQuery(query, false)
|
const queryFn = (query: any) =>
|
||||||
|
this.internalQuery(query, { connect: false, disableCoercion: true })
|
||||||
return await this.queryWithReturning(json, queryFn)
|
return await this.queryWithReturning(json, queryFn)
|
||||||
} finally {
|
} finally {
|
||||||
await this.disconnect()
|
await this.disconnect()
|
||||||
|
|
|
@ -279,9 +279,9 @@ module OracleModule {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private internalConvertType(column: OracleColumn): string {
|
private internalConvertType(column: OracleColumn): { type: string } {
|
||||||
if (this.isBooleanType(column)) {
|
if (this.isBooleanType(column)) {
|
||||||
return FieldTypes.BOOLEAN
|
return { type: FieldTypes.BOOLEAN }
|
||||||
}
|
}
|
||||||
|
|
||||||
return convertSqlType(column.type)
|
return convertSqlType(column.type)
|
||||||
|
@ -328,7 +328,7 @@ module OracleModule {
|
||||||
fieldSchema = {
|
fieldSchema = {
|
||||||
autocolumn: OracleIntegration.isAutoColumn(oracleColumn),
|
autocolumn: OracleIntegration.isAutoColumn(oracleColumn),
|
||||||
name: columnName,
|
name: columnName,
|
||||||
type: this.internalConvertType(oracleColumn),
|
...this.internalConvertType(oracleColumn),
|
||||||
}
|
}
|
||||||
table.schema[columnName] = fieldSchema
|
table.schema[columnName] = fieldSchema
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,6 @@ module PostgresModule {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const type: string = convertSqlType(column.data_type)
|
|
||||||
const identity = !!(
|
const identity = !!(
|
||||||
column.identity_generation ||
|
column.identity_generation ||
|
||||||
column.identity_start ||
|
column.identity_start ||
|
||||||
|
@ -240,7 +239,7 @@ module PostgresModule {
|
||||||
tables[tableName].schema[columnName] = {
|
tables[tableName].schema[columnName] = {
|
||||||
autocolumn: isAuto,
|
autocolumn: isAuto,
|
||||||
name: columnName,
|
name: columnName,
|
||||||
type,
|
...convertSqlType(column.data_type),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,9 @@ const SQL_DATE_TYPE_MAP = {
|
||||||
date: FieldTypes.DATETIME,
|
date: FieldTypes.DATETIME,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const SQL_DATE_ONLY_TYPES = ["date"]
|
||||||
|
const SQL_TIME_ONLY_TYPES = ["time"]
|
||||||
|
|
||||||
const SQL_STRING_TYPE_MAP = {
|
const SQL_STRING_TYPE_MAP = {
|
||||||
varchar: FieldTypes.STRING,
|
varchar: FieldTypes.STRING,
|
||||||
char: FieldTypes.STRING,
|
char: FieldTypes.STRING,
|
||||||
|
@ -85,9 +88,9 @@ export function breakExternalTableId(tableId: string | undefined) {
|
||||||
return {}
|
return {}
|
||||||
}
|
}
|
||||||
const parts = tableId.split(DOUBLE_SEPARATOR)
|
const parts = tableId.split(DOUBLE_SEPARATOR)
|
||||||
let tableName = parts.pop()
|
let datasourceId = parts.shift()
|
||||||
// if they need joined
|
// if they need joined
|
||||||
let datasourceId = parts.join(DOUBLE_SEPARATOR)
|
let tableName = parts.join(DOUBLE_SEPARATOR)
|
||||||
return { datasourceId, tableName }
|
return { datasourceId, tableName }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,12 +140,20 @@ export function breakRowIdField(_id: string | { _id: string }): any[] {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function convertSqlType(type: string) {
|
export function convertSqlType(type: string) {
|
||||||
|
let foundType = FieldTypes.STRING
|
||||||
|
const lcType = type.toLowerCase()
|
||||||
for (let [external, internal] of Object.entries(SQL_TYPE_MAP)) {
|
for (let [external, internal] of Object.entries(SQL_TYPE_MAP)) {
|
||||||
if (type.toLowerCase().includes(external)) {
|
if (lcType.includes(external)) {
|
||||||
return internal
|
foundType = internal
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return FieldTypes.STRING
|
const schema: any = { type: foundType }
|
||||||
|
if (foundType === FieldTypes.DATETIME) {
|
||||||
|
schema.dateOnly = SQL_DATE_ONLY_TYPES.includes(lcType)
|
||||||
|
schema.timeOnly = SQL_TIME_ONLY_TYPES.includes(lcType)
|
||||||
|
}
|
||||||
|
return schema
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSqlQuery(query: SqlQuery | string): SqlQuery {
|
export function getSqlQuery(query: SqlQuery | string): SqlQuery {
|
||||||
|
|
|
@ -100,10 +100,10 @@ class Orchestrator {
|
||||||
let automation = this._automation
|
let automation = this._automation
|
||||||
const app = await this.getApp()
|
const app = await this.getApp()
|
||||||
let stopped = false
|
let stopped = false
|
||||||
let loopStep
|
let loopStep = null
|
||||||
|
|
||||||
let stepCount = 0
|
let stepCount = 0
|
||||||
let loopStepNumber
|
let loopStepNumber = null
|
||||||
let loopSteps = []
|
let loopSteps = []
|
||||||
for (let step of automation.definition.steps) {
|
for (let step of automation.definition.steps) {
|
||||||
stepCount++
|
stepCount++
|
||||||
|
@ -117,15 +117,17 @@ class Orchestrator {
|
||||||
if (loopStep) {
|
if (loopStep) {
|
||||||
input = await processObject(loopStep.inputs, this._context)
|
input = await processObject(loopStep.inputs, this._context)
|
||||||
}
|
}
|
||||||
let iterations = loopStep ? input.binding.length : 1
|
let iterations = loopStep
|
||||||
|
? Array.isArray(input.binding)
|
||||||
|
? input.binding.length
|
||||||
|
: automationUtils.stringSplit(input.binding).length
|
||||||
|
: 1
|
||||||
let iterationCount = 0
|
let iterationCount = 0
|
||||||
for (let index = 0; index < iterations; index++) {
|
for (let index = 0; index < iterations; index++) {
|
||||||
let originalStepInput = cloneDeep(step.inputs)
|
let originalStepInput = cloneDeep(step.inputs)
|
||||||
|
|
||||||
// Handle if the user has set a max iteration count or if it reaches the max limit set by us
|
// Handle if the user has set a max iteration count or if it reaches the max limit set by us
|
||||||
if (loopStep) {
|
if (loopStep) {
|
||||||
// lets first of all handle the input
|
|
||||||
// if the input is array then use it, if it is a string then split it on every new line
|
|
||||||
let newInput = await processObject(
|
let newInput = await processObject(
|
||||||
loopStep.inputs,
|
loopStep.inputs,
|
||||||
cloneDeep(this._context)
|
cloneDeep(this._context)
|
||||||
|
@ -134,9 +136,6 @@ class Orchestrator {
|
||||||
newInput,
|
newInput,
|
||||||
loopStep.schema.inputs
|
loopStep.schema.inputs
|
||||||
)
|
)
|
||||||
this._context.steps[loopStepNumber] = {
|
|
||||||
currentItem: newInput.binding[index],
|
|
||||||
}
|
|
||||||
|
|
||||||
let tempOutput = { items: loopSteps, iterations: iterationCount }
|
let tempOutput = { items: loopSteps, iterations: iterationCount }
|
||||||
if (
|
if (
|
||||||
|
@ -154,6 +153,20 @@ class Orchestrator {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let item
|
||||||
|
if (
|
||||||
|
typeof loopStep.inputs.binding === "string" &&
|
||||||
|
loopStep.inputs.option === "String"
|
||||||
|
) {
|
||||||
|
item = automationUtils.stringSplit(newInput.binding)
|
||||||
|
} else {
|
||||||
|
item = loopStep.inputs.binding
|
||||||
|
}
|
||||||
|
|
||||||
|
this._context.steps[loopStepNumber] = {
|
||||||
|
currentItem: item[index],
|
||||||
|
}
|
||||||
|
|
||||||
// The "Loop" binding in the front end is "fake", so replace it here so the context can understand it
|
// The "Loop" binding in the front end is "fake", so replace it here so the context can understand it
|
||||||
// Pretty hacky because we need to account for the row object
|
// Pretty hacky because we need to account for the row object
|
||||||
for (let [key, value] of Object.entries(originalStepInput)) {
|
for (let [key, value] of Object.entries(originalStepInput)) {
|
||||||
|
@ -178,7 +191,6 @@ class Orchestrator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
|
index === parseInt(env.AUTOMATION_MAX_ITERATIONS) ||
|
||||||
index === loopStep.inputs.iterations
|
index === loopStep.inputs.iterations
|
||||||
|
@ -192,10 +204,25 @@ class Orchestrator {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let isFailure = false
|
||||||
if (
|
if (
|
||||||
this._context.steps[loopStepNumber]?.currentItem ===
|
typeof this._context.steps[loopStepNumber]?.currentItem === "object"
|
||||||
loopStep.inputs.failure
|
|
||||||
) {
|
) {
|
||||||
|
isFailure = Object.keys(
|
||||||
|
this._context.steps[loopStepNumber].currentItem
|
||||||
|
).some(value => {
|
||||||
|
return (
|
||||||
|
this._context.steps[loopStepNumber].currentItem[value] ===
|
||||||
|
loopStep.inputs.failure
|
||||||
|
)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
isFailure =
|
||||||
|
this._context.steps[loopStepNumber]?.currentItem ===
|
||||||
|
loopStep.inputs.failure
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isFailure) {
|
||||||
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
this.updateContextAndOutput(loopStepNumber, step, tempOutput, {
|
||||||
status: AutomationErrors.FAILURE_CONDITION,
|
status: AutomationErrors.FAILURE_CONDITION,
|
||||||
success: false,
|
success: false,
|
||||||
|
@ -286,18 +313,16 @@ class Orchestrator {
|
||||||
|
|
||||||
module.exports = (input, callback) => {
|
module.exports = (input, callback) => {
|
||||||
const appId = input.data.event.appId
|
const appId = input.data.event.appId
|
||||||
doInAppContext(appId, () => {
|
doInAppContext(appId, async () => {
|
||||||
const automationOrchestrator = new Orchestrator(
|
const automationOrchestrator = new Orchestrator(
|
||||||
input.data.automation,
|
input.data.automation,
|
||||||
input.data.event
|
input.data.event
|
||||||
)
|
)
|
||||||
automationOrchestrator
|
try {
|
||||||
.execute()
|
const response = await automationOrchestrator.execute()
|
||||||
.then(response => {
|
callback(null, response)
|
||||||
callback(null, response)
|
} catch (err) {
|
||||||
})
|
callback(err)
|
||||||
.catch(err => {
|
}
|
||||||
callback(err)
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -191,14 +191,13 @@ class QueryRunner {
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = (input, callback) => {
|
module.exports = (input, callback) => {
|
||||||
doInAppContext(input.appId, () => {
|
doInAppContext(input.appId, async () => {
|
||||||
const Runner = new QueryRunner(input)
|
const Runner = new QueryRunner(input)
|
||||||
Runner.execute()
|
try {
|
||||||
.then(response => {
|
const response = await Runner.execute()
|
||||||
callback(null, response)
|
callback(null, response)
|
||||||
})
|
} catch (err) {
|
||||||
.catch(err => {
|
callback(err)
|
||||||
callback(err)
|
}
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,11 @@ const { budibaseTempDir } = require("../budibaseDir")
|
||||||
const fs = require("fs")
|
const fs = require("fs")
|
||||||
const { join } = require("path")
|
const { join } = require("path")
|
||||||
const uuid = require("uuid/v4")
|
const uuid = require("uuid/v4")
|
||||||
const { doWithDB } = require("@budibase/backend-core/db")
|
const {
|
||||||
|
doWithDB,
|
||||||
|
dangerousGetDB,
|
||||||
|
closeDB,
|
||||||
|
} = require("@budibase/backend-core/db")
|
||||||
const { ObjectStoreBuckets } = require("../../constants")
|
const { ObjectStoreBuckets } = require("../../constants")
|
||||||
const {
|
const {
|
||||||
upload,
|
upload,
|
||||||
|
@ -151,14 +155,18 @@ exports.streamBackup = async appId => {
|
||||||
* @return {*} either a readable stream or a string
|
* @return {*} either a readable stream or a string
|
||||||
*/
|
*/
|
||||||
exports.exportDB = async (dbName, { stream, filter, exportName } = {}) => {
|
exports.exportDB = async (dbName, { stream, filter, exportName } = {}) => {
|
||||||
return doWithDB(dbName, async db => {
|
// streaming a DB dump is a bit more complicated, can't close DB
|
||||||
// Stream the dump if required
|
if (stream) {
|
||||||
if (stream) {
|
const db = dangerousGetDB(dbName)
|
||||||
const memStream = new MemoryStream()
|
const memStream = new MemoryStream()
|
||||||
db.dump(memStream, { filter })
|
memStream.on("end", async () => {
|
||||||
return memStream
|
await closeDB(db)
|
||||||
}
|
})
|
||||||
|
db.dump(memStream, { filter })
|
||||||
|
return memStream
|
||||||
|
}
|
||||||
|
|
||||||
|
return doWithDB(dbName, async db => {
|
||||||
// Write the dump to file if required
|
// Write the dump to file if required
|
||||||
if (exportName) {
|
if (exportName) {
|
||||||
const path = join(budibaseTempDir(), exportName)
|
const path = join(budibaseTempDir(), exportName)
|
||||||
|
|
|
@ -1014,10 +1014,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.0.130-alpha.0":
|
"@budibase/backend-core@1.0.138":
|
||||||
version "1.0.130-alpha.0"
|
version "1.0.138"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.130-alpha.0.tgz#f6da46473f52d3e513a5eb7f352ae3bde6e61b78"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.138.tgz#5297d6cf5b9ec8c15f0a6df4c7d8273b8ac900f0"
|
||||||
integrity sha512-DPuqEN8/OHFWPpUcfofjQ33lijsAKGDKc0DEF0QgLJOp2kMtBJa80tGjzTxccCZaFkCC2P5p+8kkMxKZQ6vYdA==
|
integrity sha512-1qN/5urKX8bBXwEz266Z94rco8dTI7VqIh75m8ZcqrAfoUpjvZJS76gZxfc5U/QWPwrgVFnLtYvnEjaLbGEflg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@techpass/passport-openidconnect" "^0.3.0"
|
"@techpass/passport-openidconnect" "^0.3.0"
|
||||||
aws-sdk "^2.901.0"
|
aws-sdk "^2.901.0"
|
||||||
|
@ -1091,12 +1091,12 @@
|
||||||
svelte-flatpickr "^3.2.3"
|
svelte-flatpickr "^3.2.3"
|
||||||
svelte-portal "^1.0.0"
|
svelte-portal "^1.0.0"
|
||||||
|
|
||||||
"@budibase/pro@1.0.130-alpha.0":
|
"@budibase/pro@1.0.138":
|
||||||
version "1.0.130-alpha.0"
|
version "1.0.138"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.130-alpha.0.tgz#ddae5dc39992d7f1c4f021d1e4f5effff687a183"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.138.tgz#cacbebe5ce93eb533af62a794a638944c2c61544"
|
||||||
integrity sha512-R8DvPQ6hpLChOSp0BONwrCHOgYrYDO4r2tF8KzEg4uycZ+jbaKQJs2lZ8wdkCbXGjAHIcRNt+4RKUfa9r2epJw==
|
integrity sha512-4ABlUZvl2h8sd8awJATf3KJeoFWV/8SoqdbKiH1ICdUcM/6dad7nhbJ15QqJL+Uuh/+mN2yEbr8V6Un2+yF+CA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.0.130-alpha.0"
|
"@budibase/backend-core" "1.0.138"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@budibase/standard-components@^0.9.139":
|
"@budibase/standard-components@^0.9.139":
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/string-templates",
|
"name": "@budibase/string-templates",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Handlebars wrapper for Budibase templating.",
|
"description": "Handlebars wrapper for Budibase templating.",
|
||||||
"main": "src/index.cjs",
|
"main": "src/index.cjs",
|
||||||
"module": "dist/bundle.mjs",
|
"module": "dist/bundle.mjs",
|
||||||
|
|
|
@ -70,7 +70,7 @@ function createTemplate(string, opts) {
|
||||||
* @param {object|array} object The input structure which is to be recursed, it is important to note that
|
* @param {object|array} object The input structure which is to be recursed, it is important to note that
|
||||||
* if the structure contains any cycles then this will fail.
|
* if the structure contains any cycles then this will fail.
|
||||||
* @param {object} context The context that handlebars should fill data from.
|
* @param {object} context The context that handlebars should fill data from.
|
||||||
* @param {object|undefined} opts optional - specify some options for processing.
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||||
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
|
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
|
||||||
*/
|
*/
|
||||||
module.exports.processObject = async (object, context, opts) => {
|
module.exports.processObject = async (object, context, opts) => {
|
||||||
|
@ -101,7 +101,7 @@ module.exports.processObject = async (object, context, opts) => {
|
||||||
* then nothing will occur.
|
* then nothing will occur.
|
||||||
* @param {string} string The template string which is the filled from the context object.
|
* @param {string} string The template string which is the filled from the context object.
|
||||||
* @param {object} context An object of information which will be used to enrich the string.
|
* @param {object} context An object of information which will be used to enrich the string.
|
||||||
* @param {object|undefined} opts optional - specify some options for processing.
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||||
* @returns {Promise<string>} The enriched string, all templates should have been replaced if they can be.
|
* @returns {Promise<string>} The enriched string, all templates should have been replaced if they can be.
|
||||||
*/
|
*/
|
||||||
module.exports.processString = async (string, context, opts) => {
|
module.exports.processString = async (string, context, opts) => {
|
||||||
|
@ -115,7 +115,7 @@ module.exports.processString = async (string, context, opts) => {
|
||||||
* @param {object|array} object The input structure which is to be recursed, it is important to note that
|
* @param {object|array} object The input structure which is to be recursed, it is important to note that
|
||||||
* if the structure contains any cycles then this will fail.
|
* if the structure contains any cycles then this will fail.
|
||||||
* @param {object} context The context that handlebars should fill data from.
|
* @param {object} context The context that handlebars should fill data from.
|
||||||
* @param {object|undefined} opts optional - specify some options for processing.
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||||
* @returns {object|array} The structure input, as fully updated as possible.
|
* @returns {object|array} The structure input, as fully updated as possible.
|
||||||
*/
|
*/
|
||||||
module.exports.processObjectSync = (object, context, opts) => {
|
module.exports.processObjectSync = (object, context, opts) => {
|
||||||
|
@ -136,7 +136,7 @@ module.exports.processObjectSync = (object, context, opts) => {
|
||||||
* then nothing will occur. This is a pure sync call and therefore does not have the full functionality of the async call.
|
* then nothing will occur. This is a pure sync call and therefore does not have the full functionality of the async call.
|
||||||
* @param {string} string The template string which is the filled from the context object.
|
* @param {string} string The template string which is the filled from the context object.
|
||||||
* @param {object} context An object of information which will be used to enrich the string.
|
* @param {object} context An object of information which will be used to enrich the string.
|
||||||
* @param {object|undefined} opts optional - specify some options for processing.
|
* @param {object|undefined} [opts] optional - specify some options for processing.
|
||||||
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
* @returns {string} The enriched string, all templates should have been replaced if they can be.
|
||||||
*/
|
*/
|
||||||
module.exports.processStringSync = (string, context, opts) => {
|
module.exports.processStringSync = (string, context, opts) => {
|
||||||
|
@ -194,7 +194,7 @@ module.exports.makePropSafe = property => {
|
||||||
/**
|
/**
|
||||||
* Checks whether or not a template string contains totally valid syntax (simply tries running it)
|
* Checks whether or not a template string contains totally valid syntax (simply tries running it)
|
||||||
* @param string The string to test for valid syntax - this may contain no templates and will be considered valid.
|
* @param string The string to test for valid syntax - this may contain no templates and will be considered valid.
|
||||||
* @param opts optional - specify some options for processing.
|
* @param [opts] optional - specify some options for processing.
|
||||||
* @returns {boolean} Whether or not the input string is valid.
|
* @returns {boolean} Whether or not the input string is valid.
|
||||||
*/
|
*/
|
||||||
module.exports.isValid = (string, opts) => {
|
module.exports.isValid = (string, opts) => {
|
||||||
|
@ -205,6 +205,7 @@ module.exports.isValid = (string, opts) => {
|
||||||
"array",
|
"array",
|
||||||
"cannot read property",
|
"cannot read property",
|
||||||
"undefined",
|
"undefined",
|
||||||
|
"json at position 0",
|
||||||
]
|
]
|
||||||
// this is a portion of a specific string always output by handlebars in the case of a syntax error
|
// this is a portion of a specific string always output by handlebars in the case of a syntax error
|
||||||
const invalidCases = [`expecting '`]
|
const invalidCases = [`expecting '`]
|
||||||
|
|
|
@ -360,6 +360,13 @@ describe("Test the literal helper", () => {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe("Test that JSONpase helper", () => {
|
||||||
|
it("should state that the JSONparse helper is valid", async () => {
|
||||||
|
const output = isValid(`{{ JSONparse input }}`)
|
||||||
|
expect(output).toBe(true)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
describe("Cover a few complex use cases", () => {
|
describe("Cover a few complex use cases", () => {
|
||||||
it("should allow use of three different collection helpers", async () => {
|
it("should allow use of three different collection helpers", async () => {
|
||||||
const output = await processString(
|
const output = await processString(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "@budibase/worker",
|
"name": "@budibase/worker",
|
||||||
"email": "hi@budibase.com",
|
"email": "hi@budibase.com",
|
||||||
"version": "1.0.130-alpha.0",
|
"version": "1.0.142",
|
||||||
"description": "Budibase background service",
|
"description": "Budibase background service",
|
||||||
"main": "src/index.ts",
|
"main": "src/index.ts",
|
||||||
"repository": {
|
"repository": {
|
||||||
|
@ -31,9 +31,9 @@
|
||||||
"author": "Budibase",
|
"author": "Budibase",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@budibase/backend-core": "^1.0.130-alpha.0",
|
"@budibase/backend-core": "^1.0.142",
|
||||||
"@budibase/pro": "1.0.130-alpha.0",
|
"@budibase/pro": "1.0.142",
|
||||||
"@budibase/string-templates": "^1.0.130-alpha.0",
|
"@budibase/string-templates": "^1.0.142",
|
||||||
"@koa/router": "^8.0.0",
|
"@koa/router": "^8.0.0",
|
||||||
"@sentry/node": "6.17.7",
|
"@sentry/node": "6.17.7",
|
||||||
"@techpass/passport-openidconnect": "^0.3.0",
|
"@techpass/passport-openidconnect": "^0.3.0",
|
||||||
|
|
|
@ -293,10 +293,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
|
||||||
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
|
||||||
|
|
||||||
"@budibase/backend-core@1.0.130-alpha.0":
|
"@budibase/backend-core@1.0.138":
|
||||||
version "1.0.130-alpha.0"
|
version "1.0.138"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.130-alpha.0.tgz#f6da46473f52d3e513a5eb7f352ae3bde6e61b78"
|
resolved "https://registry.yarnpkg.com/@budibase/backend-core/-/backend-core-1.0.138.tgz#5297d6cf5b9ec8c15f0a6df4c7d8273b8ac900f0"
|
||||||
integrity sha512-DPuqEN8/OHFWPpUcfofjQ33lijsAKGDKc0DEF0QgLJOp2kMtBJa80tGjzTxccCZaFkCC2P5p+8kkMxKZQ6vYdA==
|
integrity sha512-1qN/5urKX8bBXwEz266Z94rco8dTI7VqIh75m8ZcqrAfoUpjvZJS76gZxfc5U/QWPwrgVFnLtYvnEjaLbGEflg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@techpass/passport-openidconnect" "^0.3.0"
|
"@techpass/passport-openidconnect" "^0.3.0"
|
||||||
aws-sdk "^2.901.0"
|
aws-sdk "^2.901.0"
|
||||||
|
@ -321,12 +321,12 @@
|
||||||
uuid "^8.3.2"
|
uuid "^8.3.2"
|
||||||
zlib "^1.0.5"
|
zlib "^1.0.5"
|
||||||
|
|
||||||
"@budibase/pro@1.0.130-alpha.0":
|
"@budibase/pro@1.0.138":
|
||||||
version "1.0.130-alpha.0"
|
version "1.0.138"
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.130-alpha.0.tgz#ddae5dc39992d7f1c4f021d1e4f5effff687a183"
|
resolved "https://registry.yarnpkg.com/@budibase/pro/-/pro-1.0.138.tgz#cacbebe5ce93eb533af62a794a638944c2c61544"
|
||||||
integrity sha512-R8DvPQ6hpLChOSp0BONwrCHOgYrYDO4r2tF8KzEg4uycZ+jbaKQJs2lZ8wdkCbXGjAHIcRNt+4RKUfa9r2epJw==
|
integrity sha512-4ABlUZvl2h8sd8awJATf3KJeoFWV/8SoqdbKiH1ICdUcM/6dad7nhbJ15QqJL+Uuh/+mN2yEbr8V6Un2+yF+CA==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@budibase/backend-core" "1.0.130-alpha.0"
|
"@budibase/backend-core" "1.0.138"
|
||||||
node-fetch "^2.6.1"
|
node-fetch "^2.6.1"
|
||||||
|
|
||||||
"@cspotcode/source-map-consumer@0.8.0":
|
"@cspotcode/source-map-consumer@0.8.0":
|
||||||
|
|
Loading…
Reference in New Issue