@@ -33,4 +70,48 @@
/* Fix layout due to LH 0 on heading */
margin-bottom: 16px;
}
+
+ .dropzone {
+ text-align: center;
+ display: flex;
+ align-items: center;
+ flex-direction: column;
+ border-radius: 10px;
+ transition: all 0.3s;
+ }
+
+ .uploaded {
+ color: var(--blue);
+ }
+
+ input[type="file"] {
+ display: none;
+ }
+
+ label {
+ font-family: var(--font-sans);
+ cursor: pointer;
+ font-weight: 500;
+ box-sizing: border-box;
+ overflow: hidden;
+ border-radius: var(--border-radius-s);
+ color: var(--ink);
+ padding: var(--spacing-m) var(--spacing-l);
+ transition: all 0.2s ease 0s;
+ display: inline-flex;
+ text-rendering: optimizeLegibility;
+ min-width: auto;
+ outline: none;
+ font-feature-settings: "case" 1, "rlig" 1, "calt" 0;
+ -webkit-box-align: center;
+ user-select: none;
+ flex-shrink: 0;
+ align-items: center;
+ justify-content: center;
+ width: 100%;
+ background-color: var(--grey-2);
+ font-size: var(--font-size-xs);
+ line-height: normal;
+ border: var(--border-transparent);
+ }
diff --git a/packages/builder/src/pages/index.svelte b/packages/builder/src/pages/index.svelte
index 7de3a2bb35..5aa99be35b 100644
--- a/packages/builder/src/pages/index.svelte
+++ b/packages/builder/src/pages/index.svelte
@@ -4,7 +4,7 @@
import AppList from "components/start/AppList.svelte"
import { get } from "builderStore/api"
import CreateAppModal from "components/start/CreateAppModal.svelte"
- import { Button, Heading, Modal } from "@budibase/bbui"
+ import { Button, Heading, Modal, Spacer } from "@budibase/bbui"
import TemplateList from "components/start/TemplateList.svelte"
import analytics from "analytics"
@@ -43,13 +43,22 @@
modal.show()
}
+ function initiateAppImport() {
+ template = { fromFile: true }
+ modal.show()
+ }
+
checkIfKeysAndApps()
@@ -103,4 +112,9 @@
color: white;
font-weight: 500;
}
+
+ .button-group {
+ display: flex;
+ flex-direction: row;
+ }
diff --git a/packages/builder/yarn.lock b/packages/builder/yarn.lock
index fb269dda5e..803b961fcd 100644
--- a/packages/builder/yarn.lock
+++ b/packages/builder/yarn.lock
@@ -2995,6 +2995,11 @@ dotenv@^8.2.0:
resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a"
integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw==
+downloadjs@^1.4.7:
+ version "1.4.7"
+ resolved "https://registry.yarnpkg.com/downloadjs/-/downloadjs-1.4.7.tgz#f69f96f940e0d0553dac291139865a3cd0101e3c"
+ integrity sha1-9p+W+UDg0FU9rCkROYZaPNAQHjw=
+
duplexer@~0.1.1:
version "0.1.2"
resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6"
diff --git a/packages/client/src/api/api.js b/packages/client/src/api/api.js
index 5509221d5c..e5e41a6753 100644
--- a/packages/client/src/api/api.js
+++ b/packages/client/src/api/api.js
@@ -20,9 +20,10 @@ const makeApiCall = async ({ method, url, body, json = true }) => {
const requestBody = json ? JSON.stringify(body) : body
let headers = {
Accept: "application/json",
- "Content-Type": "application/json",
+ ...(json && { "Content-Type": "application/json" }),
"x-budibase-app-id": window["##BUDIBASE_APP_ID##"],
}
+
if (!window["##BUDIBASE_IN_BUILDER##"]) {
headers["x-budibase-type"] = "client"
}
diff --git a/packages/client/src/api/auth.js b/packages/client/src/api/auth.js
index ddaaa7a491..9b2988c69d 100644
--- a/packages/client/src/api/auth.js
+++ b/packages/client/src/api/auth.js
@@ -1,4 +1,6 @@
import API from "./api"
+import { enrichRows } from "./rows"
+import { TableNames } from "../constants"
/**
* Performs a log in request.
@@ -15,3 +17,15 @@ export const logIn = async ({ email, password }) => {
body: { email, password },
})
}
+
+/**
+ * Fetches the currently logged in user object
+ */
+export const fetchSelf = async () => {
+ const user = await API.get({ url: "/api/self" })
+ if (user?._id) {
+ return (await enrichRows([user], TableNames.USERS))[0]
+ } else {
+ return null
+ }
+}
diff --git a/packages/client/src/components/ClientApp.svelte b/packages/client/src/components/ClientApp.svelte
index 659f34568b..d2dce14d34 100644
--- a/packages/client/src/components/ClientApp.svelte
+++ b/packages/client/src/components/ClientApp.svelte
@@ -4,12 +4,7 @@
import Component from "./Component.svelte"
import NotificationDisplay from "./NotificationDisplay.svelte"
import SDK from "../sdk"
- import {
- createDataStore,
- initialise,
- screenStore,
- notificationStore,
- } from "../store"
+ import { createDataStore, initialise, screenStore, authStore } from "../store"
// Provide contexts
setContext("sdk", SDK)
@@ -22,6 +17,7 @@
// Load app config
onMount(async () => {
await initialise()
+ await authStore.actions.fetchUser()
loaded = true
})
diff --git a/packages/client/src/components/Component.svelte b/packages/client/src/components/Component.svelte
index 208ba21718..140d71ce80 100644
--- a/packages/client/src/components/Component.svelte
+++ b/packages/client/src/components/Component.svelte
@@ -4,7 +4,7 @@
import * as ComponentLibrary from "@budibase/standard-components"
import Router from "./Router.svelte"
import { enrichProps, propsAreSame } from "../utils/componentProps"
- import { bindingStore, builderStore } from "../store"
+ import { authStore, bindingStore, builderStore } from "../store"
export let definition = {}
@@ -23,7 +23,7 @@
$: constructor = getComponentConstructor(definition._component)
$: children = definition._children || []
$: id = definition._id
- $: enrichComponentProps(definition, $dataContext, $bindingStore)
+ $: enrichComponentProps(definition, $dataContext, $bindingStore, $authStore)
$: updateProps(enrichedProps)
$: styles = definition._styles
@@ -67,8 +67,8 @@
}
// Enriches any string component props using handlebars
- const enrichComponentProps = async (definition, context, bindingStore) => {
- enrichedProps = await enrichProps(definition, context, bindingStore)
+ const enrichComponentProps = async (definition, context, bindings, user) => {
+ enrichedProps = await enrichProps(definition, context, bindings, user)
}
// Returns a unique key to let svelte know when to remount components.
diff --git a/packages/client/src/constants.js b/packages/client/src/constants.js
new file mode 100644
index 0000000000..f5bdb4bb10
--- /dev/null
+++ b/packages/client/src/constants.js
@@ -0,0 +1,3 @@
+export const TableNames = {
+ USERS: "ta_users",
+}
diff --git a/packages/client/src/store/auth.js b/packages/client/src/store/auth.js
index d2ce04b604..29ded50ac7 100644
--- a/packages/client/src/store/auth.js
+++ b/packages/client/src/store/auth.js
@@ -3,9 +3,10 @@ import { writable, get } from "svelte/store"
import { initialise } from "./initialise"
import { routeStore } from "./routes"
import { builderStore } from "./builder"
+import { TableNames } from "../constants"
const createAuthStore = () => {
- const store = writable("")
+ const store = writable(null)
const goToDefaultRoute = () => {
// Setting the active route forces an update of the active screen ID,
@@ -15,16 +16,20 @@ const createAuthStore = () => {
// Navigating updates the URL to reflect this route
routeStore.actions.navigate("/")
}
+
+ // Logs a user in
const logIn = async ({ email, password }) => {
const user = await API.logIn({ email, password })
if (!user.error) {
- store.set(user.token)
+ store.set(user)
await initialise()
goToDefaultRoute()
}
}
+
+ // Logs a user out
const logOut = async () => {
- store.set("")
+ store.set(null)
const appId = get(builderStore).appId
if (appId) {
for (let environment of ["local", "cloud"]) {
@@ -35,9 +40,26 @@ const createAuthStore = () => {
goToDefaultRoute()
}
+ // Fetches the user object if someone is logged in and has reloaded the page
+ const fetchUser = async () => {
+ // Fetch the first user if inside the builder
+ if (get(builderStore).inBuilder) {
+ const users = await API.fetchTableData(TableNames.USERS)
+ if (!users.error && users[0] != null) {
+ store.set(users[0])
+ }
+ }
+
+ // Or fetch the current user from localstorage in a real app
+ else {
+ const user = await API.fetchSelf()
+ store.set(user)
+ }
+ }
+
return {
subscribe: store.subscribe,
- actions: { logIn, logOut },
+ actions: { logIn, logOut, fetchUser },
}
}
diff --git a/packages/client/src/utils/componentProps.js b/packages/client/src/utils/componentProps.js
index 7b322ec80f..fb421ca9fb 100644
--- a/packages/client/src/utils/componentProps.js
+++ b/packages/client/src/utils/componentProps.js
@@ -21,7 +21,7 @@ export const propsAreSame = (a, b) => {
* Enriches component props.
* Data bindings are enriched, and button actions are enriched.
*/
-export const enrichProps = async (props, dataContexts, dataBindings) => {
+export const enrichProps = async (props, dataContexts, dataBindings, user) => {
// Exclude all private props that start with an underscore
let validProps = {}
Object.entries(props)
@@ -35,6 +35,7 @@ export const enrichProps = async (props, dataContexts, dataBindings) => {
const context = {
...dataContexts,
...dataBindings,
+ user,
data: dataContexts[dataContexts.closestComponentId],
data_draft: dataContexts[`${dataContexts.closestComponentId}_draft`],
}
diff --git a/packages/server/package.json b/packages/server/package.json
index 2ee2c79e22..56e4d17627 100644
--- a/packages/server/package.json
+++ b/packages/server/package.json
@@ -22,7 +22,8 @@
"maintainer": "Budibase",
"icon": "./build/icons/",
"target": [
- "deb"
+ "deb",
+ "AppImage"
],
"category": "Development"
},
diff --git a/packages/server/src/api/controllers/application.js b/packages/server/src/api/controllers/application.js
index 91c79f1961..e899a2dca9 100644
--- a/packages/server/src/api/controllers/application.js
+++ b/packages/server/src/api/controllers/application.js
@@ -105,10 +105,16 @@ async function createInstance(template) {
// replicate the template data to the instance DB
if (template) {
- const templatePath = await downloadTemplate(...template.key.split("/"))
- const dbDumpReadStream = fs.createReadStream(
- join(templatePath, "db", "dump.txt")
- )
+ let dbDumpReadStream
+
+ if (template.fileImportPath) {
+ dbDumpReadStream = fs.createReadStream(template.fileImportPath)
+ } else {
+ const templatePath = await downloadTemplate(...template.key.split("/"))
+ dbDumpReadStream = fs.createReadStream(
+ join(templatePath, "db", "dump.txt")
+ )
+ }
const { ok } = await db.load(dbDumpReadStream)
if (!ok) {
throw "Error loading database dump from template."
diff --git a/packages/server/src/api/controllers/auth.js b/packages/server/src/api/controllers/auth.js
index f9c3ef945f..af6e0b2ee2 100644
--- a/packages/server/src/api/controllers/auth.js
+++ b/packages/server/src/api/controllers/auth.js
@@ -57,3 +57,17 @@ exports.authenticate = async ctx => {
ctx.throw(401, "Invalid credentials.")
}
}
+
+exports.fetchSelf = async ctx => {
+ const { userId, appId } = ctx.user
+ if (!userId || !appId) {
+ ctx.body = {}
+ } else {
+ const database = new CouchDB(appId)
+ const user = await database.get(userId)
+ if (user) {
+ delete user.password
+ }
+ ctx.body = user
+ }
+}
diff --git a/packages/server/src/api/controllers/backup.js b/packages/server/src/api/controllers/backup.js
new file mode 100644
index 0000000000..d021dca91f
--- /dev/null
+++ b/packages/server/src/api/controllers/backup.js
@@ -0,0 +1,41 @@
+const { performDump } = require("../../utilities/templates")
+const path = require("path")
+const os = require("os")
+const fs = require("fs-extra")
+
+exports.exportAppDump = async function(ctx) {
+ const { appId } = ctx.query
+
+ const backupsDir = path.join(os.homedir(), ".budibase", "backups")
+ fs.ensureDirSync(backupsDir)
+
+ const backupIdentifier = `${appId} Backup: ${new Date()}.txt`
+
+ await performDump({
+ dir: backupsDir,
+ appId,
+ name: backupIdentifier,
+ })
+
+ ctx.status = 200
+
+ const backupFile = path.join(backupsDir, backupIdentifier)
+
+ ctx.attachment(backupIdentifier)
+ ctx.body = fs.createReadStream(backupFile)
+ // ctx.body = {
+ // url: `/api/backups/download/${backupIdentifier}`,
+ // }
+}
+
+// exports.downloadAppDump = async function(ctx) {
+// const fileName = ctx.params.fileName
+
+// const backupsDir = path.join(os.homedir(), ".budibase", "backups")
+// fs.ensureDirSync(backupsDir)
+
+// const backupFile = path.join(backupsDir, fileName)
+
+// ctx.attachment(fileName)
+// ctx.body = fs.createReadStream(backupFile)
+// }
diff --git a/packages/server/src/api/controllers/static/index.js b/packages/server/src/api/controllers/static/index.js
index 4f3d8d1611..2096b3039e 100644
--- a/packages/server/src/api/controllers/static/index.js
+++ b/packages/server/src/api/controllers/static/index.js
@@ -177,7 +177,6 @@ exports.serveApp = async function(ctx) {
})
const appHbs = fs.readFileSync(`${__dirname}/templates/app.hbs`, "utf8")
- console.log(appHbs)
ctx.body = await processString(appHbs, {
head,
body: html,
diff --git a/packages/server/src/api/controllers/view/index.js b/packages/server/src/api/controllers/view/index.js
index 0b5b18a93c..c4e8c1e372 100644
--- a/packages/server/src/api/controllers/view/index.js
+++ b/packages/server/src/api/controllers/view/index.js
@@ -83,7 +83,7 @@ const controller = {
ctx.message = `View ${ctx.params.viewName} saved successfully.`
},
exportView: async ctx => {
- const view = ctx.request.body
+ const view = ctx.query.view
const format = ctx.query.format
// Fetch view rows
@@ -102,14 +102,6 @@ const controller = {
const filename = `${view.name}.${format}`
fs.writeFileSync(join(os.tmpdir(), filename), exportedFile)
- ctx.body = {
- url: `/api/views/export/download/${filename}`,
- name: view.name,
- }
- },
- downloadExport: async ctx => {
- const filename = ctx.params.fileName
-
ctx.attachment(filename)
ctx.body = fs.createReadStream(join(os.tmpdir(), filename))
},
diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.js
index c76eb82643..ea0ed4b875 100644
--- a/packages/server/src/api/index.js
+++ b/packages/server/src/api/index.js
@@ -5,6 +5,7 @@ const zlib = require("zlib")
const { budibaseAppsDir } = require("../utilities/budibaseDir")
const { isDev } = require("../utilities")
const { mainRoutes, authRoutes, staticRoutes } = require("./routes")
+const pkg = require("../../package.json")
const router = new Router()
const env = require("../environment")
@@ -32,6 +33,7 @@ router
await next()
})
.use("/health", ctx => (ctx.status = 200))
+ .use("/version", ctx => (ctx.body = pkg.version))
.use(authenticated)
// error handling middleware
diff --git a/packages/server/src/api/routes/auth.js b/packages/server/src/api/routes/auth.js
index b4b68e8929..83053305c9 100644
--- a/packages/server/src/api/routes/auth.js
+++ b/packages/server/src/api/routes/auth.js
@@ -4,5 +4,6 @@ const controller = require("../controllers/auth")
const router = Router()
router.post("/api/authenticate", controller.authenticate)
+router.get("/api/self", controller.fetchSelf)
module.exports = router
diff --git a/packages/server/src/api/routes/backup.js b/packages/server/src/api/routes/backup.js
new file mode 100644
index 0000000000..283bec39a4
--- /dev/null
+++ b/packages/server/src/api/routes/backup.js
@@ -0,0 +1,15 @@
+const Router = require("@koa/router")
+const controller = require("../controllers/backup")
+const authorized = require("../../middleware/authorized")
+const { BUILDER } = require("../../utilities/security/permissions")
+
+const router = Router()
+
+router.get("/api/backups/export", authorized(BUILDER), controller.exportAppDump)
+// .get(
+// "/api/backups/download/:fileName",
+// authorized(BUILDER),
+// controller.downloadAppDump
+// )
+
+module.exports = router
diff --git a/packages/server/src/api/routes/index.js b/packages/server/src/api/routes/index.js
index 68b0c3fc2b..002d2ec805 100644
--- a/packages/server/src/api/routes/index.js
+++ b/packages/server/src/api/routes/index.js
@@ -21,6 +21,7 @@ const permissionRoutes = require("./permission")
const datasourceRoutes = require("./datasource")
const queryRoutes = require("./query")
const hostingRoutes = require("./hosting")
+const backupRoutes = require("./backup")
exports.mainRoutes = [
deployRoutes,
@@ -42,6 +43,7 @@ exports.mainRoutes = [
datasourceRoutes,
queryRoutes,
hostingRoutes,
+ backupRoutes,
// these need to be handled last as they still use /api/:tableId
// this could be breaking as koa may recognise other routes as this
tableRoutes,
diff --git a/packages/server/src/api/routes/view.js b/packages/server/src/api/routes/view.js
index 17277b346c..4a32b4c592 100644
--- a/packages/server/src/api/routes/view.js
+++ b/packages/server/src/api/routes/view.js
@@ -26,10 +26,5 @@ router
)
.post("/api/views", authorized(BUILDER), usage, viewController.save)
.post("/api/views/export", authorized(BUILDER), viewController.exportView)
- .get(
- "/api/views/export/download/:fileName",
- authorized(BUILDER),
- viewController.downloadExport
- )
module.exports = router
diff --git a/packages/server/src/utilities/templates.js b/packages/server/src/utilities/templates.js
index d5b5d5e257..7383e3115d 100644
--- a/packages/server/src/utilities/templates.js
+++ b/packages/server/src/utilities/templates.js
@@ -10,7 +10,6 @@ const streamPipeline = promisify(stream.pipeline)
const { budibaseAppsDir } = require("./budibaseDir")
const env = require("../environment")
const CouchDB = require("../db")
-const { DocumentTypes } = require("../db/utils")
const DEFAULT_TEMPLATES_BUCKET =
"prod-budi-templates.s3-eu-west-1.amazonaws.com"
@@ -56,6 +55,15 @@ exports.downloadTemplate = async function(type, name) {
return dirName
}
+async function performDump({ dir, appId, name = "dump.txt" }) {
+ const writeStream = fs.createWriteStream(join(dir, name))
+ // perform couch dump
+ const instanceDb = new CouchDB(appId)
+ await instanceDb.dump(writeStream, {})
+}
+
+exports.performDump = performDump
+
exports.exportTemplateFromApp = async function({ templateName, appId }) {
// Copy frontend files
const templatesDir = join(
@@ -67,13 +75,6 @@ exports.exportTemplateFromApp = async function({ templateName, appId }) {
"db"
)
fs.ensureDirSync(templatesDir)
- const writeStream = fs.createWriteStream(join(templatesDir, "dump.txt"))
- // perform couch dump
- const instanceDb = new CouchDB(appId)
- await instanceDb.dump(writeStream, {
- filter: doc => {
- return !doc._id.startsWith(DocumentTypes.USER)
- },
- })
+ await performDump({ dir: templatesDir, appId })
return templatesDir
}
diff --git a/packages/standard-components/package.json b/packages/standard-components/package.json
index 51eda7815e..767ac30c0e 100644
--- a/packages/standard-components/package.json
+++ b/packages/standard-components/package.json
@@ -38,7 +38,7 @@
"license": "MIT",
"gitHead": "62ebf3cedcd7e9b2494b4f8cbcfb90927609b491",
"dependencies": {
- "@budibase/bbui": "^1.52.4",
+ "@budibase/bbui": "^1.55.1",
"@budibase/svelte-ag-grid": "^0.0.16",
"apexcharts": "^3.22.1",
"flatpickr": "^4.6.6",
diff --git a/packages/standard-components/src/grid/Component.svelte b/packages/standard-components/src/grid/Component.svelte
index 3492301082..3004622bfd 100644
--- a/packages/standard-components/src/grid/Component.svelte
+++ b/packages/standard-components/src/grid/Component.svelte
@@ -135,8 +135,7 @@
}
const updateRow = async row => {
- const schema = (await API.fetchTableDefinition(row.tableId)).schema
- await API.updateRow(schema, { data: row })
+ await API.updateRow(row)
}
const deleteRows = async () => {
diff --git a/packages/standard-components/yarn.lock b/packages/standard-components/yarn.lock
index 682c048276..8b4ffdcf3e 100644
--- a/packages/standard-components/yarn.lock
+++ b/packages/standard-components/yarn.lock
@@ -39,10 +39,10 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
-"@budibase/bbui@^1.52.4":
- version "1.52.4"
- resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.52.4.tgz#ae3c17e1f49f14e65831703958bcddc6e64afd24"
- integrity sha512-/wiv5dSyvXLgy2/zGEslnCsjwE8qqng1D8k5ScSOPEyMab8tzzd1XxfZAN9rp84zIMgAXeH6s5a4j4riR+jVkg==
+"@budibase/bbui@^1.55.1":
+ version "1.55.1"
+ resolved "https://registry.yarnpkg.com/@budibase/bbui/-/bbui-1.55.1.tgz#291fb6fa10479b49f078d3a911ad0ed42c2e6b12"
+ integrity sha512-bxsHBwkOqCtuFz89e0hAXwvwycfS4xPPrEge5PxK1Lh3uqetO4bXoIxYaIDjfi2Ku7CYIzEmOwSloNaQWeTF4g==
dependencies:
markdown-it "^12.0.2"
quill "^1.3.7"
diff --git a/packages/string-templates/package.json b/packages/string-templates/package.json
index 5c5da0a920..0ce825c9c0 100644
--- a/packages/string-templates/package.json
+++ b/packages/string-templates/package.json
@@ -13,8 +13,8 @@
"test": "jest"
},
"dependencies": {
+ "@budibase/handlebars-helpers": "^0.11.1",
"handlebars": "^4.7.6",
- "handlebars-helpers": "^0.10.0",
"handlebars-utils": "^1.0.6",
"helper-date": "^1.0.1",
"lodash": "^4.17.20"
@@ -22,7 +22,6 @@
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-json": "^4.1.0",
- "@rollup/plugin-replace": "^2.3.4",
"doctrine": "^3.0.0",
"jest": "^26.6.3",
"rollup": "^2.36.2",
diff --git a/packages/string-templates/rollup.config.js b/packages/string-templates/rollup.config.js
index bca8e14e53..355ad3bcdb 100644
--- a/packages/string-templates/rollup.config.js
+++ b/packages/string-templates/rollup.config.js
@@ -3,7 +3,6 @@ import resolve from "rollup-plugin-node-resolve"
import builtins from "rollup-plugin-node-builtins"
import globals from "rollup-plugin-node-globals"
import json from "@rollup/plugin-json"
-import replace from "@rollup/plugin-replace"
import { terser } from "rollup-plugin-terser"
const production = !process.env.ROLLUP_WATCH
@@ -19,18 +18,6 @@ export default {
},
],
plugins: [
- // this replacement is a crazy hack to fix an issue that
- // rollup has with the handlebars-helper package
- // if we don't do this then the browser will always error
- // with the isNumber function being unavailable
- replace({
- include: [
- "node_modules/handlebars-helpers/lib/**",
- "node_modules/handlebar-utils/lib/**",
- ],
- "utils.isNumber(": "!isNaN(",
- "isNumber(": "!isNaN(",
- }),
resolve({
mainFields: ["module", "main"],
preferBuiltins: true,
diff --git a/packages/string-templates/src/helpers/external.js b/packages/string-templates/src/helpers/external.js
index a137c25cef..6cdf976be5 100644
--- a/packages/string-templates/src/helpers/external.js
+++ b/packages/string-templates/src/helpers/external.js
@@ -1,10 +1,10 @@
-const helpers = require("handlebars-helpers")
+const helpers = require("@budibase/handlebars-helpers")
const dateHelper = require("helper-date")
const { HelperFunctionBuiltin } = require("./constants")
/**
* full list of supported helpers can be found here:
- * https://github.com/helpers/handlebars-helpers
+ * https://github.com/Budibase/handlebars-helpers
*/
const EXTERNAL_FUNCTION_COLLECTIONS = [
diff --git a/packages/string-templates/yarn.lock b/packages/string-templates/yarn.lock
index 0cbed748ed..9cb3dc1fd4 100644
--- a/packages/string-templates/yarn.lock
+++ b/packages/string-templates/yarn.lock
@@ -270,6 +270,38 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@budibase/handlebars-helpers@^0.11.0":
+ version "0.11.1"
+ resolved "https://registry.yarnpkg.com/@budibase/handlebars-helpers/-/handlebars-helpers-0.11.1.tgz#fe8672612fb4ad8fd3bad338ee15759f45e421eb"
+ integrity sha512-s72LhOhlHk43QYGVcqjogaGa4h4e6y6X1AfshqWBWceTRYBs/9tUnoYDUiRJ/Mt3WoTmx8Hj5GOZekSqrUsOFQ==
+ dependencies:
+ arr-flatten "^1.1.0"
+ array-sort "^0.1.4"
+ define-property "^1.0.0"
+ extend-shallow "^3.0.2"
+ "falsey" "^0.3.2"
+ for-in "^1.0.2"
+ for-own "^1.0.0"
+ get-object "^0.2.0"
+ get-value "^2.0.6"
+ handlebars "^4.0.11"
+ handlebars-utils "^1.0.6"
+ has-value "^1.0.0"
+ helper-date "^1.0.1"
+ helper-markdown "^1.0.0"
+ helper-md "^0.2.2"
+ html-tag "^2.0.0"
+ is-even "^1.0.0"
+ is-glob "^4.0.0"
+ is-number "^4.0.0"
+ kind-of "^6.0.0"
+ logging-helpers "^1.0.0"
+ micromatch "^3.1.4"
+ relative "^3.0.2"
+ striptags "^3.1.0"
+ to-gfm-code-block "^0.1.1"
+ year "^0.2.1"
+
"@cnakazawa/watch@^1.0.3":
version "1.0.4"
resolved "https://registry.yarnpkg.com/@cnakazawa/watch/-/watch-1.0.4.tgz#f864ae85004d0fcab6f50be9141c4da368d1656a"
@@ -485,14 +517,6 @@
dependencies:
"@rollup/pluginutils" "^3.0.8"
-"@rollup/plugin-replace@^2.3.4":
- version "2.3.4"
- resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz#7dd84c17755d62b509577f2db37eb524d7ca88ca"
- integrity sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==
- dependencies:
- "@rollup/pluginutils" "^3.1.0"
- magic-string "^0.25.7"
-
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
@@ -1472,16 +1496,6 @@ create-ecdh@^4.0.0:
bn.js "^4.1.0"
elliptic "^6.5.3"
-create-frame@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/create-frame/-/create-frame-1.0.0.tgz#8b95f2691e3249b6080443e33d0bad9f8f6975aa"
- integrity sha1-i5XyaR4ySbYIBEPjPQutn49pdao=
- dependencies:
- define-property "^0.2.5"
- extend-shallow "^2.0.1"
- isobject "^3.0.0"
- lazy-cache "^2.0.2"
-
create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/create-hash/-/create-hash-1.2.0.tgz#889078af11a63756bcfb59bd221996be3a9ef196"
@@ -2153,48 +2167,6 @@ gulp-header@^1.7.1:
lodash.template "^4.4.0"
through2 "^2.0.0"
-handlebars-helper-create-frame@^0.1.0:
- version "0.1.0"
- resolved "https://registry.yarnpkg.com/handlebars-helper-create-frame/-/handlebars-helper-create-frame-0.1.0.tgz#8aa51d10aeb6408fcc6605d40d77356288487a03"
- integrity sha1-iqUdEK62QI/MZgXUDXc1YohIegM=
- dependencies:
- create-frame "^1.0.0"
- isobject "^3.0.0"
-
-handlebars-helpers@^0.10.0:
- version "0.10.0"
- resolved "https://registry.yarnpkg.com/handlebars-helpers/-/handlebars-helpers-0.10.0.tgz#663d49e718928eafbead1473419ed7bc24bcd45a"
- integrity sha512-QiyhQz58u/DbuV41VnfpE0nhy6YCH4vB514ajysV8SoKmP+DxU+pR+fahVyNECHj+jiwEN2VrvxD/34/yHaLUg==
- dependencies:
- arr-flatten "^1.1.0"
- array-sort "^0.1.4"
- create-frame "^1.0.0"
- define-property "^1.0.0"
- "falsey" "^0.3.2"
- for-in "^1.0.2"
- for-own "^1.0.0"
- get-object "^0.2.0"
- get-value "^2.0.6"
- handlebars "^4.0.11"
- handlebars-helper-create-frame "^0.1.0"
- handlebars-utils "^1.0.6"
- has-value "^1.0.0"
- helper-date "^1.0.1"
- helper-markdown "^1.0.0"
- helper-md "^0.2.2"
- html-tag "^2.0.0"
- is-even "^1.0.0"
- is-glob "^4.0.0"
- is-number "^4.0.0"
- kind-of "^6.0.0"
- lazy-cache "^2.0.2"
- logging-helpers "^1.0.0"
- micromatch "^3.1.4"
- relative "^3.0.2"
- striptags "^3.1.0"
- to-gfm-code-block "^0.1.1"
- year "^0.2.1"
-
handlebars-utils@^1.0.2, handlebars-utils@^1.0.4, handlebars-utils@^1.0.6:
version "1.0.6"
resolved "https://registry.yarnpkg.com/handlebars-utils/-/handlebars-utils-1.0.6.tgz#cb9db43362479054782d86ffe10f47abc76357f9"
@@ -3219,7 +3191,7 @@ kleur@^3.0.3:
resolved "https://registry.yarnpkg.com/kleur/-/kleur-3.0.3.tgz#a79c9ecc86ee1ce3fa6206d1216c501f147fc07e"
integrity sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==
-lazy-cache@^2.0.1, lazy-cache@^2.0.2:
+lazy-cache@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/lazy-cache/-/lazy-cache-2.0.2.tgz#b9190a4f913354694840859f8a8f7084d8822264"
integrity sha1-uRkKT5EzVGlIQIWfio9whNiCImQ=
@@ -4790,9 +4762,9 @@ typescript@^4.1.3:
integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg==
uglify-js@^3.1.4:
- version "3.12.4"
- resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.4.tgz#93de48bb76bb3ec0fc36563f871ba46e2ee5c7ee"
- integrity sha512-L5i5jg/SHkEqzN18gQMTWsZk3KelRsfD1wUVNqtq0kzqWQqcJjyL8yc1o8hJgRrWqrAl2mUFbhfznEIoi7zi2A==
+ version "3.12.6"
+ resolved "https://registry.yarnpkg.com/uglify-js/-/uglify-js-3.12.6.tgz#f884584fcc42e10bca70db5cb32e8625c2c42535"
+ integrity sha512-aqWHe3DfQmZUDGWBbabZ2eQnJlQd1fKlMUu7gV+MiTuDzdgDw31bI3wA2jLLsV/hNcDP26IfyEgSVoft5+0SVw==
union-value@^1.0.0:
version "1.0.1"