@@ -94,7 +101,7 @@
transition: border 130ms ease-out;
border: 1px solid transparent;
}
- .app-row:hover {
+ .app-row:not(.unclickable):hover {
cursor: pointer;
border-color: var(--spectrum-global-color-gray-300);
}
diff --git a/packages/client/manifest.json b/packages/client/manifest.json
index 64d9366423..6c7a254cfb 100644
--- a/packages/client/manifest.json
+++ b/packages/client/manifest.json
@@ -4719,10 +4719,22 @@
]
}
],
- "context": {
- "type": "schema",
- "scope": "local"
- }
+ "context": [
+ {
+ "type": "schema",
+ "scope": "local"
+ },
+ {
+ "type": "static",
+ "values": [
+ {
+ "label": "Selected Rows",
+ "key": "selectedRows",
+ "type": "array"
+ }
+ ]
+ }
+ ]
},
"daterangepicker": {
"name": "Date Range",
@@ -5610,37 +5622,50 @@
]
}
],
- "context": {
- "type": "static",
- "suffix": "provider",
- "values": [
- {
- "label": "Rows",
- "key": "rows",
- "type": "array"
- },
- {
- "label": "Extra Info",
- "key": "info",
- "type": "string"
- },
- {
- "label": "Rows Length",
- "key": "rowsLength",
- "type": "number"
- },
- {
- "label": "Schema",
- "key": "schema",
- "type": "object"
- },
- {
- "label": "Page Number",
- "key": "pageNumber",
- "type": "number"
- }
- ]
- }
+ "context": [
+ {
+ "type": "static",
+ "suffix": "provider",
+ "values": [
+ {
+ "label": "Rows",
+ "key": "rows",
+ "type": "array"
+ },
+ {
+ "label": "Extra Info",
+ "key": "info",
+ "type": "string"
+ },
+ {
+ "label": "Rows Length",
+ "key": "rowsLength",
+ "type": "number"
+ },
+ {
+ "label": "Schema",
+ "key": "schema",
+ "type": "object"
+ },
+ {
+ "label": "Page Number",
+ "key": "pageNumber",
+ "type": "number"
+ }
+ ]
+ },
+ {
+ "type": "static",
+ "suffix": "table",
+ "values": [
+ {
+ "label": "Selected Rows",
+ "key": "selectedRows",
+ "type": "array"
+ }
+ ]
+ }
+ ]
},
"cardsblock": {
"block": true,
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 6694022b98..6d6af91dcc 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -113,6 +113,9 @@
// List of context keys which we use inside bindings
let knownContextKeyMap = {}
+ // Cleanup function to stop observing context changes when unmounting
+ let unobserve
+
// Set up initial state for each new component instance
$: initialise(instance)
@@ -311,6 +314,11 @@
// Force an initial enrichment of the new settings
enrichComponentSettings(get(context), settingsDefinitionMap)
+
+ // Start observing changes in context now that we are initialised
+ if (!unobserve) {
+ unobserve = context.actions.observeChanges(handleContextChange)
+ }
}
// Extracts a map of all context keys which are required by action settings
@@ -567,8 +575,8 @@
}
}
- // Register an unregister component instance
onMount(() => {
+ // Register this component instance for external access
if ($appStore.isDevApp) {
if (!componentStore.actions.isComponentRegistered(id)) {
componentStore.actions.registerInstance(id, {
@@ -581,16 +589,17 @@
state: store,
})
}
- return () => {
- if (componentStore.actions.isComponentRegistered(id)) {
- componentStore.actions.unregisterInstance(id)
- }
+ }
+ return () => {
+ // Unregister component
+ if (componentStore.actions.isComponentRegistered(id)) {
+ componentStore.actions.unregisterInstance(id)
}
+
+ // Stop observing context changes
+ unobserve?.()
}
})
-
- // Observe changes to context
- onMount(() => context.actions.observeChanges(handleContextChange))
{#if constructor && initialSettings && (visible || inSelectedPath) && !builderHidden}
diff --git a/packages/client/src/components/app/blocks/CardsBlock.svelte b/packages/client/src/components/app/blocks/CardsBlock.svelte
index e0985a8979..008fa7e730 100644
--- a/packages/client/src/components/app/blocks/CardsBlock.svelte
+++ b/packages/client/src/components/app/blocks/CardsBlock.svelte
@@ -69,7 +69,10 @@
}
const col = linkColumn || "_id"
const split = url.split("/:")
- return `${split[0]}/{{ ${safe(repeaterId)}.${safe(col)} }}`
+ if (split.length > 1) {
+ return `${split[0]}/{{ ${safe(repeaterId)}.${safe(col)} }}`
+ }
+ return url
}
// Load the datasource schema so we can determine column types
diff --git a/packages/client/src/components/app/table/Table.svelte b/packages/client/src/components/app/table/Table.svelte
index 4da7dc314b..0afaff0a36 100644
--- a/packages/client/src/components/app/table/Table.svelte
+++ b/packages/client/src/components/app/table/Table.svelte
@@ -3,6 +3,7 @@
import { Table } from "@budibase/bbui"
import SlotRenderer from "./SlotRenderer.svelte"
import { canBeSortColumn } from "@budibase/shared-core"
+ import Provider from "../../context/Provider.svelte"
export let dataProvider
export let columns
@@ -55,6 +56,11 @@
}
}
+ // Build our data context
+ $: dataContext = {
+ selectedRows,
+ }
+
const getFields = (
schema,
customColumns,
@@ -156,27 +162,29 @@
-
+
+
+
{#if allowSelectRows && selectedRows.length}
{selectedRows.length} row{selectedRows.length === 1 ? "" : "s"} selected
diff --git a/packages/client/src/stores/rowSelection.js b/packages/client/src/stores/rowSelection.js
index de40ae595e..4c0a196678 100644
--- a/packages/client/src/stores/rowSelection.js
+++ b/packages/client/src/stores/rowSelection.js
@@ -5,7 +5,7 @@ const createRowSelectionStore = () => {
function updateSelection(componentId, tableId, selectedRows) {
store.update(state => {
- state[componentId] = { tableId: tableId, selectedRows: selectedRows }
+ state[componentId] = { tableId, selectedRows }
return state
})
}
diff --git a/packages/client/src/utils/buttonActions.js b/packages/client/src/utils/buttonActions.js
index ef529985b2..259128f6d4 100644
--- a/packages/client/src/utils/buttonActions.js
+++ b/packages/client/src/utils/buttonActions.js
@@ -341,7 +341,10 @@ const exportDataHandler = async action => {
format: action.parameters.type,
columns: action.parameters.columns,
})
- download(data, `${selection.tableId}.${action.parameters.type}`)
+ download(
+ new Blob([data], { type: "text/plain" }),
+ `${selection.tableId}.${action.parameters.type}`
+ )
} catch (error) {
notificationStore.actions.error("There was an error exporting the data")
}
diff --git a/packages/server/package.json b/packages/server/package.json
index 9d385c7664..e600e36bd3 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -103,6 +103,7 @@
"pouchdb-all-dbs": "1.1.1",
"pouchdb-find": "7.2.2",
"redis": "4",
+ "serialize-error": "^7.0.1",
"server-destroy": "1.0.1",
"snowflake-promise": "^4.5.0",
"socket.io": "4.6.1",
diff --git a/packages/server/scripts/dev/manage.js b/packages/server/scripts/dev/manage.js
index 1c7a70931b..509e9a05ac 100644
--- a/packages/server/scripts/dev/manage.js
+++ b/packages/server/scripts/dev/manage.js
@@ -38,7 +38,6 @@ async function init() {
SELF_HOSTED: "1",
DISABLE_ACCOUNT_PORTAL: "1",
MULTI_TENANCY: "",
- DISABLE_THREADING: "1",
SERVICE: "app-service",
DEPLOYMENT_ENVIRONMENT: "development",
BB_ADMIN_USER_EMAIL: "",
diff --git a/packages/server/src/automations/utils.ts b/packages/server/src/automations/utils.ts
index 0c28787f67..360802df6a 100644
--- a/packages/server/src/automations/utils.ts
+++ b/packages/server/src/automations/utils.ts
@@ -16,9 +16,9 @@ import {
} from "@budibase/types"
import sdk from "../sdk"
import { automationsEnabled } from "../features"
+import { helpers, REBOOT_CRON } from "@budibase/shared-core"
import tracer from "dd-trace"
-const REBOOT_CRON = "@reboot"
const WH_STEP_ID = definitions.WEBHOOK.stepId
const CRON_STEP_ID = definitions.CRON.stepId
let Runner: Thread
@@ -198,6 +198,13 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
!isRebootTrigger(automation) &&
trigger?.inputs.cron
) {
+ const cronExp = trigger.inputs.cron
+ const validation = helpers.cron.validate(cronExp)
+ if (!validation.valid) {
+ throw new Error(
+ `Invalid automation CRON "${cronExp}" - ${validation.err.join(", ")}`
+ )
+ }
// make a job id rather than letting Bull decide, makes it easier to handle on way out
const jobId = `${appId}_cron_${newid()}`
const job: any = await automationQueue.add(
@@ -205,7 +212,7 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
automation,
event: { appId, timestamp: Date.now() },
},
- { repeat: { cron: trigger.inputs.cron }, jobId }
+ { repeat: { cron: cronExp }, jobId }
)
// Assign cron job ID from bull so we can remove it later if the cron trigger is removed
trigger.cronJobId = job.id
diff --git a/packages/server/src/environment.ts b/packages/server/src/environment.ts
index ba3aa280e2..8e6866d5e4 100644
--- a/packages/server/src/environment.ts
+++ b/packages/server/src/environment.ts
@@ -97,11 +97,7 @@ const environment = {
APP_MIGRATION_TIMEOUT: parseIntSafe(process.env.APP_MIGRATION_TIMEOUT),
JS_RUNNER_MEMORY_LIMIT:
parseIntSafe(process.env.JS_RUNNER_MEMORY_LIMIT) || 64,
-}
-
-// threading can cause memory issues with node-ts in development
-if (coreEnv.isDev() && environment.DISABLE_THREADING == null) {
- environment._set("DISABLE_THREADING", "1")
+ LOG_JS_ERRORS: process.env.LOG_JS_ERRORS,
}
// clean up any environment variable edge cases
diff --git a/packages/server/src/jsRunner/index.ts b/packages/server/src/jsRunner/index.ts
index 1936b0ef45..e39dab1313 100644
--- a/packages/server/src/jsRunner/index.ts
+++ b/packages/server/src/jsRunner/index.ts
@@ -1,8 +1,9 @@
import vm from "vm"
import env from "../environment"
-import { setJSRunner } from "@budibase/string-templates"
-import { context, timers } from "@budibase/backend-core"
+import { setJSRunner, setOnErrorLog } from "@budibase/string-templates"
+import { context, logging, timers } from "@budibase/backend-core"
import tracer from "dd-trace"
+import { serializeError } from "serialize-error"
type TrackerFn = (f: () => T) => T
@@ -58,4 +59,10 @@ export function init() {
)
})
})
+
+ if (env.LOG_JS_ERRORS) {
+ setOnErrorLog((error: Error) => {
+ logging.logWarn(JSON.stringify(serializeError(error)))
+ })
+ }
}
diff --git a/packages/server/src/threads/utils.ts b/packages/server/src/threads/utils.ts
index a0f3bbdc47..cd547cacae 100644
--- a/packages/server/src/threads/utils.ts
+++ b/packages/server/src/threads/utils.ts
@@ -2,6 +2,7 @@ import { QueryVariable } from "./definitions"
import env from "../environment"
import * as db from "../db"
import { redis, db as dbCore } from "@budibase/backend-core"
+import * as jsRunner from "../jsRunner"
const VARIABLE_TTL_SECONDS = 3600
let client: any
@@ -29,7 +30,9 @@ export function threadSetup() {
console.debug(`[${env.FORKED_PROCESS_NAME}] thread setup skipped`)
return
}
+
console.debug(`[${env.FORKED_PROCESS_NAME}] thread setup running`)
+ jsRunner.init()
db.init()
}
diff --git a/packages/shared-core/package.json b/packages/shared-core/package.json
index edbbd1dc56..777896a7f7 100644
--- a/packages/shared-core/package.json
+++ b/packages/shared-core/package.json
@@ -14,7 +14,8 @@
"check:types": "tsc -p tsconfig.json --noEmit --paths null"
},
"dependencies": {
- "@budibase/types": "0.0.0"
+ "@budibase/types": "0.0.0",
+ "cron-validate": "1.4.5"
},
"devDependencies": {
"rimraf": "3.0.2",
diff --git a/packages/shared-core/src/constants/index.ts b/packages/shared-core/src/constants/index.ts
index a23913dd11..99fb5c2a73 100644
--- a/packages/shared-core/src/constants/index.ts
+++ b/packages/shared-core/src/constants/index.ts
@@ -99,6 +99,8 @@ export const SocketSessionTTL = 60
export const ValidQueryNameRegex = /^[^()]*$/
export const ValidColumnNameRegex = /^[_a-zA-Z0-9\s]*$/g
+export const REBOOT_CRON = "@reboot"
+
export const InvalidFileExtensions = [
"7z",
"action",
diff --git a/packages/shared-core/src/helpers/cron.ts b/packages/shared-core/src/helpers/cron.ts
new file mode 100644
index 0000000000..ca1f1badb7
--- /dev/null
+++ b/packages/shared-core/src/helpers/cron.ts
@@ -0,0 +1,47 @@
+import cronValidate from "cron-validate"
+
+const INPUT_CRON_START = "(Input cron: "
+const ERROR_SWAPS = {
+ "smaller than lower limit": "less than",
+ "bigger than upper limit": "greater than",
+ daysOfMonth: "'days of the month'",
+ daysOfWeek: "'days of the week'",
+ years: "'years'",
+ months: "'months'",
+ hours: "'hours'",
+ minutes: "'minutes'",
+ seconds: "'seconds'",
+}
+
+function improveErrors(errors: string[]): string[] {
+ const finalErrors: string[] = []
+
+ for (let error of errors) {
+ if (error.includes(INPUT_CRON_START)) {
+ error = error.split(INPUT_CRON_START)[0].trim()
+ }
+ for (let [oldErr, newErr] of Object.entries(ERROR_SWAPS)) {
+ if (error.includes(oldErr)) {
+ error = error.replace(new RegExp(oldErr, "g"), newErr)
+ }
+ }
+ finalErrors.push(error)
+ }
+ return finalErrors
+}
+
+export function validate(
+ cronExpression: string
+): { valid: false; err: string[] } | { valid: true } {
+ const result = cronValidate(cronExpression, {
+ preset: "npm-node-cron",
+ override: {
+ useSeconds: false,
+ },
+ })
+ if (!result.isValid()) {
+ return { valid: false, err: improveErrors(result.getError()) }
+ } else {
+ return { valid: true }
+ }
+}
diff --git a/packages/shared-core/src/helpers/index.ts b/packages/shared-core/src/helpers/index.ts
index fd185aa1e9..e76022b14b 100644
--- a/packages/shared-core/src/helpers/index.ts
+++ b/packages/shared-core/src/helpers/index.ts
@@ -1,2 +1,3 @@
export * from "./helpers"
export * from "./integrations"
+export * as cron from "./cron"
diff --git a/packages/shared-core/src/tests/cron.test.ts b/packages/shared-core/src/tests/cron.test.ts
new file mode 100644
index 0000000000..d56165b2b8
--- /dev/null
+++ b/packages/shared-core/src/tests/cron.test.ts
@@ -0,0 +1,22 @@
+import { expect, describe, it } from "vitest"
+import { cron } from "../helpers"
+
+describe("check valid and invalid crons", () => {
+ it("invalid - 0 0 0 11 *", () => {
+ expect(cron.validate("0 0 0 11 *")).toStrictEqual({
+ valid: false,
+ err: [expect.stringContaining("less than '1'")],
+ })
+ })
+
+ it("invalid - 5 4 32 1 1", () => {
+ expect(cron.validate("5 4 32 1 1")).toStrictEqual({
+ valid: false,
+ err: [expect.stringContaining("greater than '31'")],
+ })
+ })
+
+ it("valid - * * * * *", () => {
+ expect(cron.validate("* * * * *")).toStrictEqual({ valid: true })
+ })
+})
diff --git a/packages/string-templates/src/helpers/javascript.js b/packages/string-templates/src/helpers/javascript.js
index 99d7df10f7..4a7f602690 100644
--- a/packages/string-templates/src/helpers/javascript.js
+++ b/packages/string-templates/src/helpers/javascript.js
@@ -8,6 +8,9 @@ const { getJsHelperList } = require("./list")
let runJS
module.exports.setJSRunner = runner => (runJS = runner)
+let onErrorLog
+module.exports.setOnErrorLog = delegate => (onErrorLog = delegate)
+
// Helper utility to strip square brackets from a value
const removeSquareBrackets = value => {
if (!value || typeof value !== "string") {
@@ -56,6 +59,8 @@ module.exports.processJS = (handlebars, context) => {
const res = { data: runJS(js, sandboxContext) }
return `{{${LITERAL_MARKER} js_result-${JSON.stringify(res)}}}`
} catch (error) {
+ onErrorLog && onErrorLog(error)
+
if (error.code === "ERR_SCRIPT_EXECUTION_TIMEOUT") {
return "Timed out while executing JS"
}
diff --git a/packages/string-templates/src/index.js b/packages/string-templates/src/index.js
index 3636c0a456..bcd63d2e6f 100644
--- a/packages/string-templates/src/index.js
+++ b/packages/string-templates/src/index.js
@@ -1,3 +1,4 @@
+const vm = require("vm")
const handlebars = require("handlebars")
const { registerAll, registerMinimum } = require("./helpers/index")
const processors = require("./processors")
@@ -365,6 +366,7 @@ module.exports.doesContainString = (template, string) => {
}
module.exports.setJSRunner = javascript.setJSRunner
+module.exports.setOnErrorLog = javascript.setOnErrorLog
module.exports.convertToJS = hbs => {
const blocks = exports.findHBSBlocks(hbs)
@@ -401,3 +403,19 @@ const errors = require("./errors")
module.exports.JsErrorTimeout = errors.JsErrorTimeout
module.exports.helpersToRemoveForJs = helpersToRemoveForJs
+
+if (process && !process.env.NO_JS) {
+ /**
+ * Use polyfilled vm to run JS scripts in a browser Env
+ */
+ javascript.setJSRunner((js, context) => {
+ context = {
+ ...context,
+ alert: undefined,
+ setInterval: undefined,
+ setTimeout: undefined,
+ }
+ vm.createContext(context)
+ return vm.runInNewContext(js, context, { timeout: 1000 })
+ })
+}
diff --git a/packages/string-templates/src/index.mjs b/packages/string-templates/src/index.mjs
index bdded04b02..f54ca7e23e 100644
--- a/packages/string-templates/src/index.mjs
+++ b/packages/string-templates/src/index.mjs
@@ -1,4 +1,3 @@
-import vm from "vm"
import templates from "./index.js"
/**
@@ -20,23 +19,8 @@ export const disableEscaping = templates.disableEscaping
export const findHBSBlocks = templates.findHBSBlocks
export const convertToJS = templates.convertToJS
export const setJSRunner = templates.setJSRunner
+export const setOnErrorLog = templates.setOnErrorLog
export const FIND_ANY_HBS_REGEX = templates.FIND_ANY_HBS_REGEX
export const helpersToRemoveForJs = templates.helpersToRemoveForJs
-if (process && !process.env.NO_JS) {
- /**
- * Use polyfilled vm to run JS scripts in a browser Env
- */
- setJSRunner((js, context) => {
- context = {
- ...context,
- alert: undefined,
- setInterval: undefined,
- setTimeout: undefined,
- }
- vm.createContext(context)
- return vm.runInNewContext(js, context, { timeout: 1000 })
- })
-}
-
export * from "./errors.js"
diff --git a/yarn.lock b/yarn.lock
index 23fced15d3..1937482837 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1980,6 +1980,13 @@
resolved "https://registry.yarnpkg.com/@babel/regjsgen/-/regjsgen-0.8.0.tgz#f0ba69b075e1f05fb2825b7fad991e7adbb18310"
integrity sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==
+"@babel/runtime@^7.10.5":
+ version "7.23.9"
+ resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7"
+ integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw==
+ dependencies:
+ regenerator-runtime "^0.14.0"
+
"@babel/runtime@^7.12.5", "@babel/runtime@^7.13.10", "@babel/runtime@^7.15.4", "@babel/runtime@^7.21.0", "@babel/runtime@^7.8.4", "@babel/runtime@^7.9.2":
version "7.23.8"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650"
@@ -5465,6 +5472,11 @@
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.200.tgz#435b6035c7eba9cdf1e039af8212c9e9281e7149"
integrity sha512-YI/M/4HRImtNf3pJgbF+W6FrXovqj+T+/HpENLTooK9PnkacBsDpeP3IpHab40CClUfhNmdM2WTNP2sa2dni5Q==
+"@types/lodash@^4.14.165":
+ version "4.14.202"
+ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.202.tgz#f09dbd2fb082d507178b2f2a5c7e74bd72ff98f8"
+ integrity sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==
+
"@types/long@^4.0.0":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/long/-/long-4.0.2.tgz#b74129719fc8d11c01868010082d483b7545591a"
@@ -8622,6 +8634,13 @@ cron-parser@^4.2.1:
dependencies:
luxon "^3.2.1"
+cron-validate@1.4.5:
+ version "1.4.5"
+ resolved "https://registry.yarnpkg.com/cron-validate/-/cron-validate-1.4.5.tgz#eceb221f7558e6302e5f84c7b3a454fdf4d064c3"
+ integrity sha512-nKlOJEnYKudMn/aNyNH8xxWczlfpaazfWV32Pcx/2St51r2bxWbGhZD7uwzMcRhunA/ZNL+Htm/i0792Z59UMQ==
+ dependencies:
+ yup "0.32.9"
+
cross-spawn@^6.0.0:
version "6.0.5"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4"
@@ -14650,7 +14669,7 @@ lock@^1.1.0:
resolved "https://registry.yarnpkg.com/lock/-/lock-1.1.0.tgz#53157499d1653b136ca66451071fca615703fa55"
integrity sha512-NZQIJJL5Rb9lMJ0Yl1JoVr9GSdo4HTPsUEWsSFzB8dE8DSoiLCVavWZPi7Rnlv/o73u6I24S/XYc/NmG4l8EKA==
-lodash-es@^4.17.21:
+lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==
@@ -14800,7 +14819,7 @@ lodash.xor@^4.5.0:
resolved "https://registry.yarnpkg.com/lodash.xor/-/lodash.xor-4.5.0.tgz#4d48ed7e98095b0632582ba714d3ff8ae8fb1db6"
integrity sha512-sVN2zimthq7aZ5sPGXnSz32rZPuqcparVW50chJQe+mzTYV+IsxSsl/2gnkWWE2Of7K3myBQBqtLKOUEHJKRsQ==
-lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
+lodash@4.17.21, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.3, lodash@^4.7.0:
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
@@ -22312,6 +22331,19 @@ yocto-queue@^1.0.0:
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==
+yup@0.32.9:
+ version "0.32.9"
+ resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.9.tgz#9367bec6b1b0e39211ecbca598702e106019d872"
+ integrity sha512-Ci1qN+i2H0XpY7syDQ0k5zKQ/DoxO0LzPg8PAR/X4Mpj6DqaeCoIYEEjDJwhArh3Fa7GWbQQVDZKeXYlSH4JMg==
+ dependencies:
+ "@babel/runtime" "^7.10.5"
+ "@types/lodash" "^4.14.165"
+ lodash "^4.17.20"
+ lodash-es "^4.17.15"
+ nanoclone "^0.2.1"
+ property-expr "^2.0.4"
+ toposort "^2.0.2"
+
yup@^0.32.11:
version "0.32.11"
resolved "https://registry.yarnpkg.com/yup/-/yup-0.32.11.tgz#d67fb83eefa4698607982e63f7ca4c5ed3cf18c5"