This commit is contained in:
Keviin Åberg Kultalahti 2021-05-03 09:31:09 +02:00
parent 27ce375f17
commit 0afbf1649e
182 changed files with 753 additions and 798 deletions

View File

@ -1,9 +1,9 @@
let Pouch let Pouch
module.exports.setDB = pouch => { module.exports.setDB = (pouch) => {
Pouch = pouch Pouch = pouch
} }
module.exports.getDB = dbName => { module.exports.getDB = (dbName) => {
return new Pouch(dbName) return new Pouch(dbName)
} }

View File

@ -48,7 +48,7 @@ exports.getGroupParams = (id = "", otherProps = {}) => {
* Generates a new global user ID. * Generates a new global user ID.
* @returns {string} The new user ID which the user doc can be stored under. * @returns {string} The new user ID which the user doc can be stored under.
*/ */
exports.generateGlobalUserID = id => { exports.generateGlobalUserID = (id) => {
return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}` return `${DocumentTypes.USER}${SEPARATOR}${id || newid()}`
} }
@ -70,7 +70,7 @@ exports.getGlobalUserParams = (globalId, otherProps = {}) => {
* Generates a template ID. * Generates a template ID.
* @param ownerId The owner/user of the template, this could be global or a group level. * @param ownerId The owner/user of the template, this could be global or a group level.
*/ */
exports.generateTemplateID = ownerId => { exports.generateTemplateID = (ownerId) => {
return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}` return `${DocumentTypes.TEMPLATE}${SEPARATOR}${ownerId}${newid()}`
} }
@ -123,7 +123,7 @@ const getConfigParams = ({ type, group, user }, otherProps = {}) => {
* @param {Object} scopes - the type, group and userID scopes of the configuration. * @param {Object} scopes - the type, group and userID scopes of the configuration.
* @returns The most granular configuration document based on the scope. * @returns The most granular configuration document based on the scope.
*/ */
const determineScopedConfig = async function(db, { type, user, group }) { const determineScopedConfig = async function (db, { type, user, group }) {
const response = await db.allDocs( const response = await db.allDocs(
getConfigParams( getConfigParams(
{ type, user, group }, { type, user, group },
@ -132,7 +132,7 @@ const determineScopedConfig = async function(db, { type, user, group }) {
} }
) )
) )
const configs = response.rows.map(row => { const configs = response.rows.map((row) => {
const config = row.doc const config = row.doc
// Config is specific to a user and a group // Config is specific to a user and a group

View File

@ -4,7 +4,7 @@ const { v4 } = require("uuid")
const SALT_ROUNDS = env.SALT_ROUNDS || 10 const SALT_ROUNDS = env.SALT_ROUNDS || 10
exports.hash = async data => { exports.hash = async (data) => {
const salt = await bcrypt.genSalt(SALT_ROUNDS) const salt = await bcrypt.genSalt(SALT_ROUNDS)
return bcrypt.hash(data, salt) return bcrypt.hash(data, salt)
} }
@ -13,6 +13,6 @@ exports.compare = async (data, encrypted) => {
return bcrypt.compare(data, encrypted) return bcrypt.compare(data, encrypted)
} }
exports.newid = function() { exports.newid = function () {
return v4().replace(/-/g, "") return v4().replace(/-/g, "")
} }

View File

@ -51,7 +51,7 @@ async function authenticate(token, tokenSecret, profile, done) {
* from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport. * from couchDB rather than environment variables, using this factory is necessary for dynamically configuring passport.
* @returns Dynamically configured Passport Google Strategy * @returns Dynamically configured Passport Google Strategy
*/ */
exports.strategyFactory = async function(config) { exports.strategyFactory = async function (config) {
try { try {
const { clientID, clientSecret, callbackURL } = config const { clientID, clientSecret, callbackURL } = config

View File

@ -3,12 +3,12 @@ const env = require("../../environment")
exports.options = { exports.options = {
secretOrKey: env.JWT_SECRET, secretOrKey: env.JWT_SECRET,
jwtFromRequest: function(ctx) { jwtFromRequest: function (ctx) {
return ctx.cookies.get(Cookies.Auth) return ctx.cookies.get(Cookies.Auth)
}, },
} }
exports.authenticate = async function(jwt, done) { exports.authenticate = async function (jwt, done) {
try { try {
return done(null, jwt) return done(null, jwt)
} catch (err) { } catch (err) {

View File

@ -15,7 +15,7 @@ exports.options = {}
* @param {*} done - callback from passport to return user information and errors * @param {*} done - callback from passport to return user information and errors
* @returns The authenticated user, or errors if they occur * @returns The authenticated user, or errors if they occur
*/ */
exports.authenticate = async function(email, password, done) { exports.authenticate = async function (email, password, done) {
if (!email) return done(null, false, "Email Required.") if (!email) return done(null, false, "Email Required.")
if (!password) return done(null, false, "Password Required.") if (!password) return done(null, false, "Password Required.")

View File

@ -22,7 +22,7 @@ function confirmAppId(possibleAppId) {
* @param {object} ctx The main request body to look through. * @param {object} ctx The main request body to look through.
* @returns {string|undefined} If an appId was found it will be returned. * @returns {string|undefined} If an appId was found it will be returned.
*/ */
exports.getAppId = ctx => { exports.getAppId = (ctx) => {
const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId] const options = [ctx.headers["x-budibase-app-id"], ctx.params.appId]
if (ctx.subdomains) { if (ctx.subdomains) {
options.push(ctx.subdomains[1]) options.push(ctx.subdomains[1])
@ -41,7 +41,7 @@ exports.getAppId = ctx => {
} }
let appPath = let appPath =
ctx.request.headers.referrer || ctx.request.headers.referrer ||
ctx.path.split("/").filter(subPath => subPath.startsWith(APP_PREFIX)) ctx.path.split("/").filter((subPath) => subPath.startsWith(APP_PREFIX))
if (!appId && appPath.length !== 0) { if (!appId && appPath.length !== 0) {
appId = confirmAppId(appPath[0]) appId = confirmAppId(appPath[0])
} }
@ -101,11 +101,11 @@ exports.clearCookie = (ctx, name) => {
* @param {object} ctx The koa context object to be tested. * @param {object} ctx The koa context object to be tested.
* @return {boolean} returns true if the call is from the client lib (a built app rather than the builder). * @return {boolean} returns true if the call is from the client lib (a built app rather than the builder).
*/ */
exports.isClient = ctx => { exports.isClient = (ctx) => {
return ctx.headers["x-budibase-type"] === "client" return ctx.headers["x-budibase-type"] === "client"
} }
exports.getGlobalUserByEmail = async email => { exports.getGlobalUserByEmail = async (email) => {
const db = getDB(StaticDatabases.GLOBAL.name) const db = getDB(StaticDatabases.GLOBAL.name)
try { try {
let users = ( let users = (
@ -114,7 +114,7 @@ exports.getGlobalUserByEmail = async email => {
include_docs: true, include_docs: true,
}) })
).rows ).rows
users = users.map(user => user.doc) users = users.map((user) => user.doc)
return users.length <= 1 ? users[0] : users return users.length <= 1 ? users[0] : users
} catch (err) { } catch (err) {
if (err != null && err.name === "not_found") { if (err != null && err.name === "not_found") {

View File

@ -47,7 +47,7 @@ export default function positionDropdown(element, { anchor, align }) {
element.style[positionSide] = `${dimensions[positionSide]}px` element.style[positionSide] = `${dimensions[positionSide]}px`
element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px` element.style.left = `${calcLeftPosition(dimensions).toFixed(0)}px`
const resizeObserver = new ResizeObserver(entries => { const resizeObserver = new ResizeObserver((entries) => {
entries.forEach(() => { entries.forEach(() => {
dimensions = getDimensions() dimensions = getDimensions()
element.style[positionSide] = `${dimensions[positionSide]}px` element.style[positionSide] = `${dimensions[positionSide]}px`

View File

@ -7,7 +7,7 @@ export const createNotificationStore = () => {
const _notifications = writable([], () => { const _notifications = writable([], () => {
return () => { return () => {
// clear all the timers // clear all the timers
timeoutIds.forEach(timeoutId => { timeoutIds.forEach((timeoutId) => {
clearTimeout(timeoutId) clearTimeout(timeoutId)
}) })
_notifications.set([]) _notifications.set([])
@ -25,11 +25,11 @@ export const createNotificationStore = () => {
return return
} }
let _id = id() let _id = id()
_notifications.update(state => { _notifications.update((state) => {
return [...state, { id: _id, type, message, icon }] return [...state, { id: _id, type, message, icon }]
}) })
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
_notifications.update(state => { _notifications.update((state) => {
return state.filter(({ id }) => id !== _id) return state.filter(({ id }) => id !== _id)
}) })
}, NOTIFICATION_TIMEOUT) }, NOTIFICATION_TIMEOUT)
@ -41,21 +41,16 @@ export const createNotificationStore = () => {
return { return {
subscribe, subscribe,
send, send,
info: msg => send(msg, "info", "Info"), info: (msg) => send(msg, "info", "Info"),
error: msg => send(msg, "error", "Alert"), error: (msg) => send(msg, "error", "Alert"),
warning: msg => send(msg, "warning", "Alert"), warning: (msg) => send(msg, "warning", "Alert"),
success: msg => send(msg, "success", "CheckmarkCircle"), success: (msg) => send(msg, "success", "CheckmarkCircle"),
blockNotifications, blockNotifications,
} }
} }
function id() { function id() {
return ( return "_" + Math.random().toString(36).substr(2, 9)
"_" +
Math.random()
.toString(36)
.substr(2, 9)
)
} }
export const notifications = createNotificationStore() export const notifications = createNotificationStore()

View File

@ -1,7 +1,5 @@
export const generateID = () => { export const generateID = () => {
const rand = Math.random() const rand = Math.random().toString(32).substring(2)
.toString(32)
.substring(2)
// Starts with a letter so that its a valid DOM ID // Starts with a letter so that its a valid DOM ID
return `A${rand}` return `A${rand}`

View File

@ -1,6 +1,6 @@
const ncp = require("ncp").ncp const ncp = require("ncp").ncp
ncp("./dist", "../server/builder", function(err) { ncp("./dist", "../server/builder", function (err) {
if (err) { if (err) {
return console.error(err) return console.error(err)
} }

View File

@ -6,15 +6,13 @@
// //
Cypress.Commands.add("login", () => { Cypress.Commands.add("login", () => {
cy.getCookie("budibase:auth").then(cookie => { cy.getCookie("budibase:auth").then((cookie) => {
// Already logged in // Already logged in
if (cookie) return if (cookie) return
cy.visit(`localhost:${Cypress.env("PORT")}/builder`) cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
cy.contains("Create Test User").click() cy.contains("Create Test User").click()
cy.get("input") cy.get("input").first().type("test@test.com")
.first()
.type("test@test.com")
cy.get('input[type="password"]').type("test") cy.get('input[type="password"]').type("test")
@ -22,38 +20,26 @@ Cypress.Commands.add("login", () => {
}) })
}) })
Cypress.Commands.add("createApp", name => { Cypress.Commands.add("createApp", (name) => {
cy.visit(`localhost:${Cypress.env("PORT")}/builder`) cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
// wait for init API calls on visit // wait for init API calls on visit
cy.wait(100) cy.wait(100)
cy.contains("Create New Web App").click() cy.contains("Create New Web App").click()
cy.get("body") cy.get("body")
.then($body => { .then(($body) => {
if ($body.find("input[name=apiKey]").length) { if ($body.find("input[name=apiKey]").length) {
// input was found, do something else here // input was found, do something else here
cy.get("input[name=apiKey]") cy.get("input[name=apiKey]").type(name).should("have.value", name)
.type(name)
.should("have.value", name)
cy.contains("Next").click() cy.contains("Next").click()
} }
}) })
.then(() => { .then(() => {
cy.get(".spectrum-Modal") cy.get(".spectrum-Modal")
.within(() => { .within(() => {
cy.get("input") cy.get("input").eq(0).type(name).should("have.value", name).blur()
.eq(0)
.type(name)
.should("have.value", name)
.blur()
cy.contains("Next").click() cy.contains("Next").click()
cy.get("input") cy.get("input").eq(1).type("test@test.com").blur()
.eq(1) cy.get("input").eq(2).type("test").blur()
.type("test@test.com")
.blur()
cy.get("input")
.eq(2)
.type("test")
.blur()
cy.contains("Submit").click() cy.contains("Submit").click()
}) })
.then(() => { .then(() => {
@ -64,20 +50,16 @@ Cypress.Commands.add("createApp", name => {
}) })
}) })
Cypress.Commands.add("deleteApp", name => { Cypress.Commands.add("deleteApp", (name) => {
cy.visit(`localhost:${Cypress.env("PORT")}/builder`) cy.visit(`localhost:${Cypress.env("PORT")}/builder`)
cy.get(".apps").then($apps => { cy.get(".apps").then(($apps) => {
cy.wait(1000) cy.wait(1000)
if ($apps.find(`[data-cy="app-${name}"]`).length) { if ($apps.find(`[data-cy="app-${name}"]`).length) {
cy.get(`[data-cy="app-${name}"]`) cy.get(`[data-cy="app-${name}"]`).contains("Open").click()
.contains("Open")
.click()
cy.get("[data-cy=settings-icon]").click() cy.get("[data-cy=settings-icon]").click()
cy.get(".spectrum-Dialog").within(() => { cy.get(".spectrum-Dialog").within(() => {
cy.contains("Danger Zone").click() cy.contains("Danger Zone").click()
cy.get("input") cy.get("input").type("DELETE").blur()
.type("DELETE")
.blur()
cy.contains("Delete Entire App").click() cy.contains("Delete Entire App").click()
}) })
} }
@ -96,17 +78,12 @@ Cypress.Commands.add("createTestTableWithData", () => {
cy.addColumn("dog", "age", "Number") cy.addColumn("dog", "age", "Number")
}) })
Cypress.Commands.add("createTable", tableName => { Cypress.Commands.add("createTable", (tableName) => {
// Enter table name // Enter table name
cy.get("[data-cy=new-table]").click() cy.get("[data-cy=new-table]").click()
cy.get(".spectrum-Modal").within(() => { cy.get(".spectrum-Modal").within(() => {
cy.get("input") cy.get("input").first().type(tableName).blur()
.first() cy.get(".spectrum-ButtonGroup").contains("Create").click()
.type(tableName)
.blur()
cy.get(".spectrum-ButtonGroup")
.contains("Create")
.click()
}) })
cy.contains(tableName).should("be.visible") cy.contains(tableName).should("be.visible")
}) })
@ -118,10 +95,7 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
// Configure column // Configure column
cy.get(".spectrum-Modal").within(() => { cy.get(".spectrum-Modal").within(() => {
cy.get("input") cy.get("input").first().type(columnName).blur()
.first()
.type(columnName)
.blur()
// Unset table display column // Unset table display column
cy.contains("display column").click({ force: true }) cy.contains("display column").click({ force: true })
@ -130,18 +104,13 @@ Cypress.Commands.add("addColumn", (tableName, columnName, type) => {
}) })
}) })
Cypress.Commands.add("addRow", values => { Cypress.Commands.add("addRow", (values) => {
cy.contains("Create row").click() cy.contains("Create row").click()
cy.get(".spectrum-Modal").within(() => { cy.get(".spectrum-Modal").within(() => {
for (let i = 0; i < values.length; i++) { for (let i = 0; i < values.length; i++) {
cy.get("input") cy.get("input").eq(i).type(values[i]).blur()
.eq(i)
.type(values[i])
.blur()
} }
cy.get(".spectrum-ButtonGroup") cy.get(".spectrum-ButtonGroup").contains("Create").click()
.contains("Create")
.click()
}) })
}) })
@ -150,22 +119,12 @@ Cypress.Commands.add("createUser", (email, password, role) => {
cy.contains("Users").click() cy.contains("Users").click()
cy.contains("Create user").click() cy.contains("Create user").click()
cy.get(".spectrum-Modal").within(() => { cy.get(".spectrum-Modal").within(() => {
cy.get("input") cy.get("input").first().type(email).blur()
.first() cy.get("input").eq(1).type(password).blur()
.type(email) cy.get("select").first().select(role)
.blur()
cy.get("input")
.eq(1)
.type(password)
.blur()
cy.get("select")
.first()
.select(role)
// Save // Save
cy.get(".spectrum-ButtonGroup") cy.get(".spectrum-ButtonGroup").contains("Create User").click()
.contains("Create User")
.click()
}) })
}) })
@ -175,7 +134,7 @@ Cypress.Commands.add("addComponent", (category, component) => {
} }
cy.get(`[data-cy="component-${component}"]`).click() cy.get(`[data-cy="component-${component}"]`).click()
cy.wait(1000) cy.wait(1000)
cy.location().then(loc => { cy.location().then((loc) => {
const params = loc.pathname.split("/") const params = loc.pathname.split("/")
const componentId = params[params.length - 1] const componentId = params[params.length - 1]
cy.getComponent(componentId).should("exist") cy.getComponent(componentId).should("exist")
@ -183,7 +142,7 @@ Cypress.Commands.add("addComponent", (category, component) => {
}) })
}) })
Cypress.Commands.add("getComponent", componentId => { Cypress.Commands.add("getComponent", (componentId) => {
return cy return cy
.get("iframe") .get("iframe")
.its("0.contentDocument") .its("0.contentDocument")
@ -201,15 +160,9 @@ Cypress.Commands.add("navigateToFrontend", () => {
Cypress.Commands.add("createScreen", (screenName, route) => { Cypress.Commands.add("createScreen", (screenName, route) => {
cy.get("[data-cy=new-screen]").click() cy.get("[data-cy=new-screen]").click()
cy.get(".spectrum-Modal").within(() => { cy.get(".spectrum-Modal").within(() => {
cy.get("input") cy.get("input").eq(0).type(screenName).blur()
.eq(0)
.type(screenName)
.blur()
if (route) { if (route) {
cy.get("input") cy.get("input").eq(1).type(route).blur()
.eq(1)
.type(route)
.blur()
} }
cy.contains("Create Screen").click() cy.contains("Create Screen").click()
}) })

View File

@ -32,7 +32,7 @@ function identify(id) {
if (!analyticsEnabled || !id) return if (!analyticsEnabled || !id) return
if (posthogConfigured) posthog.identify(id) if (posthogConfigured) posthog.identify(id)
if (sentryConfigured) if (sentryConfigured)
Sentry.configureScope(scope => { Sentry.configureScope((scope) => {
scope.setUser({ id: id }) scope.setUser({ id: id })
}) })
} }
@ -73,7 +73,7 @@ if (!localStorage.getItem(APP_FIRST_STARTED_KEY)) {
localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now()) localStorage.setItem(APP_FIRST_STARTED_KEY, Date.now())
} }
const isFeedbackTimeElapsed = sinceDateStr => { const isFeedbackTimeElapsed = (sinceDateStr) => {
const sinceDate = parseFloat(sinceDateStr) const sinceDate = parseFloat(sinceDateStr)
const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000 const feedbackMilliseconds = feedbackHours * 60 * 60 * 1000
return Date.now() > sinceDate + feedbackMilliseconds return Date.now() > sinceDate + feedbackMilliseconds
@ -107,7 +107,7 @@ function highlightFeedbackIcon() {
} }
// Opt In/Out // Opt In/Out
const ifAnalyticsEnabled = func => () => { const ifAnalyticsEnabled = (func) => () => {
if (analyticsEnabled && process.env.POSTHOG_TOKEN) { if (analyticsEnabled && process.env.POSTHOG_TOKEN) {
return func() return func()
} }

View File

@ -2,7 +2,7 @@ import { store } from "./index"
import { get as svelteGet } from "svelte/store" import { get as svelteGet } from "svelte/store"
import { removeCookie, Cookies } from "./cookies" import { removeCookie, Cookies } from "./cookies"
const apiCall = method => async ( const apiCall = (method) => async (
url, url,
body, body,
headers = { "Content-Type": "application/json" } headers = { "Content-Type": "application/json" }

View File

@ -4,7 +4,7 @@ export const Cookies = {
} }
export function getCookie(cookieName) { export function getCookie(cookieName) {
return document.cookie.split(";").some(cookie => { return document.cookie.split(";").some((cookie) => {
return cookie.trim().startsWith(`${cookieName}=`) return cookie.trim().startsWith(`${cookieName}=`)
}) })
} }

View File

@ -34,7 +34,7 @@ export const getDataProviderComponents = (asset, componentId) => {
path.pop() path.pop()
// Filter by only data provider components // Filter by only data provider components
return path.filter(component => { return path.filter((component) => {
const def = store.actions.components.getDefinition(component._component) const def = store.actions.components.getDefinition(component._component)
return def?.context != null return def?.context != null
}) })
@ -54,7 +54,7 @@ export const getActionProviderComponents = (asset, componentId, actionType) => {
path.pop() path.pop()
// Filter by only data provider components // Filter by only data provider components
return path.filter(component => { return path.filter((component) => {
const def = store.actions.components.getDefinition(component._component) const def = store.actions.components.getDefinition(component._component)
return def?.actions?.includes(actionType) return def?.actions?.includes(actionType)
}) })
@ -70,7 +70,7 @@ export const getDatasourceForProvider = (asset, component) => {
} }
// If this component has a dataProvider setting, go up the stack and use it // If this component has a dataProvider setting, go up the stack and use it
const dataProviderSetting = def.settings.find(setting => { const dataProviderSetting = def.settings.find((setting) => {
return setting.type === "dataProvider" return setting.type === "dataProvider"
}) })
if (dataProviderSetting) { if (dataProviderSetting) {
@ -82,7 +82,7 @@ export const getDatasourceForProvider = (asset, component) => {
// Extract datasource from component instance // Extract datasource from component instance
const validSettingTypes = ["dataSource", "table", "schema"] const validSettingTypes = ["dataSource", "table", "schema"]
const datasourceSetting = def.settings.find(setting => { const datasourceSetting = def.settings.find((setting) => {
return validSettingTypes.includes(setting.type) return validSettingTypes.includes(setting.type)
}) })
if (!datasourceSetting) { if (!datasourceSetting) {
@ -112,7 +112,7 @@ const getContextBindings = (asset, componentId) => {
let bindings = [] let bindings = []
// Create bindings for each data provider // Create bindings for each data provider
dataProviders.forEach(component => { dataProviders.forEach((component) => {
const def = store.actions.components.getDefinition(component._component) const def = store.actions.components.getDefinition(component._component)
const contextDefinition = def.context const contextDefinition = def.context
let schema let schema
@ -127,7 +127,7 @@ const getContextBindings = (asset, componentId) => {
// Static contexts are fully defined by the components // Static contexts are fully defined by the components
schema = {} schema = {}
const values = contextDefinition.values || [] const values = contextDefinition.values || []
values.forEach(value => { values.forEach((value) => {
schema[value.key] = { name: value.label, type: "string" } schema[value.key] = { name: value.label, type: "string" }
}) })
} else if (contextDefinition.type === "schema") { } else if (contextDefinition.type === "schema") {
@ -148,7 +148,7 @@ const getContextBindings = (asset, componentId) => {
// Create bindable properties for each schema field // Create bindable properties for each schema field
const safeComponentId = makePropSafe(component._id) const safeComponentId = makePropSafe(component._id)
keys.forEach(key => { keys.forEach((key) => {
const fieldSchema = schema[key] const fieldSchema = schema[key]
// Make safe runtime binding and replace certain bindings with a // Make safe runtime binding and replace certain bindings with a
@ -197,7 +197,7 @@ const getUserBindings = () => {
}) })
const keys = Object.keys(schema).sort() const keys = Object.keys(schema).sort()
const safeUser = makePropSafe("user") const safeUser = makePropSafe("user")
keys.forEach(key => { keys.forEach((key) => {
const fieldSchema = schema[key] const fieldSchema = schema[key]
// Replace certain bindings with a new property to help display components // Replace certain bindings with a new property to help display components
let runtimeBoundKey = key let runtimeBoundKey = key
@ -224,17 +224,17 @@ const getUserBindings = () => {
/** /**
* Gets all bindable properties from URL parameters. * Gets all bindable properties from URL parameters.
*/ */
const getUrlBindings = asset => { const getUrlBindings = (asset) => {
const url = asset?.routing?.route ?? "" const url = asset?.routing?.route ?? ""
const split = url.split("/") const split = url.split("/")
let params = [] let params = []
split.forEach(part => { split.forEach((part) => {
if (part.startsWith(":") && part.length > 1) { if (part.startsWith(":") && part.length > 1) {
params.push(part.replace(/:/g, "").replace(/\?/g, "")) params.push(part.replace(/:/g, "").replace(/\?/g, ""))
} }
}) })
const safeURL = makePropSafe("url") const safeURL = makePropSafe("url")
return params.map(param => ({ return params.map((param) => ({
type: "context", type: "context",
runtimeBinding: `${safeURL}.${makePropSafe(param)}`, runtimeBinding: `${safeURL}.${makePropSafe(param)}`,
readableBinding: `URL.${param}`, readableBinding: `URL.${param}`,
@ -250,10 +250,10 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
const { type } = datasource const { type } = datasource
if (type === "query") { if (type === "query") {
const queries = get(queriesStores).list const queries = get(queriesStores).list
table = queries.find(query => query._id === datasource._id) table = queries.find((query) => query._id === datasource._id)
} else { } else {
const tables = get(tablesStore).list const tables = get(tablesStore).list
table = tables.find(table => table._id === datasource.tableId) table = tables.find((table) => table._id === datasource.tableId)
} }
if (table) { if (table) {
if (type === "view") { if (type === "view") {
@ -261,7 +261,7 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
} else if (type === "query" && isForm) { } else if (type === "query" && isForm) {
schema = {} schema = {}
const params = table.parameters || [] const params = table.parameters || []
params.forEach(param => { params.forEach((param) => {
if (param?.name) { if (param?.name) {
schema[param.name] = { ...param, type: "string" } schema[param.name] = { ...param, type: "string" }
} }
@ -279,7 +279,7 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
// Ensure there are "name" properties for all fields // Ensure there are "name" properties for all fields
if (schema) { if (schema) {
Object.keys(schema).forEach(field => { Object.keys(schema).forEach((field) => {
if (!schema[field].name) { if (!schema[field].name) {
schema[field].name = field schema[field].name = field
} }
@ -293,14 +293,14 @@ export const getSchemaForDatasource = (datasource, isForm = false) => {
* Builds a form schema given a form component. * Builds a form schema given a form component.
* A form schema is a schema of all the fields nested anywhere within a form. * A form schema is a schema of all the fields nested anywhere within a form.
*/ */
const buildFormSchema = component => { const buildFormSchema = (component) => {
let schema = {} let schema = {}
if (!component) { if (!component) {
return schema return schema
} }
const def = store.actions.components.getDefinition(component._component) const def = store.actions.components.getDefinition(component._component)
const fieldSetting = def?.settings?.find( const fieldSetting = def?.settings?.find(
setting => setting.key === "field" && setting.type.startsWith("field/") (setting) => setting.key === "field" && setting.type.startsWith("field/")
) )
if (fieldSetting && component.field) { if (fieldSetting && component.field) {
const type = fieldSetting.type.split("field/")[1] const type = fieldSetting.type.split("field/")[1]
@ -308,7 +308,7 @@ const buildFormSchema = component => {
schema[component.field] = { type } schema[component.field] = { type }
} }
} }
component._children?.forEach(child => { component._children?.forEach((child) => {
const childSchema = buildFormSchema(child) const childSchema = buildFormSchema(child)
schema = { ...schema, ...childSchema } schema = { ...schema, ...childSchema }
}) })
@ -339,7 +339,7 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
return textWithBindings return textWithBindings
} }
const convertFromProps = bindableProperties const convertFromProps = bindableProperties
.map(el => el[convertFrom]) .map((el) => el[convertFrom])
.sort((a, b) => { .sort((a, b) => {
return b.length - a.length return b.length - a.length
}) })
@ -349,7 +349,9 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
let newBoundValue = boundValue let newBoundValue = boundValue
for (let from of convertFromProps) { for (let from of convertFromProps) {
if (newBoundValue.includes(from)) { if (newBoundValue.includes(from)) {
const binding = bindableProperties.find(el => el[convertFrom] === from) const binding = bindableProperties.find(
(el) => el[convertFrom] === from
)
newBoundValue = newBoundValue.replace(from, binding[convertTo]) newBoundValue = newBoundValue.replace(from, binding[convertTo])
} }
} }

View File

@ -12,12 +12,16 @@ export const automationStore = getAutomationStore()
export const themeStore = getThemeStore() export const themeStore = getThemeStore()
export const hostingStore = getHostingStore() export const hostingStore = getHostingStore()
export const currentAsset = derived(store, $store => { export const currentAsset = derived(store, ($store) => {
const type = $store.currentFrontEndType const type = $store.currentFrontEndType
if (type === FrontendTypes.SCREEN) { if (type === FrontendTypes.SCREEN) {
return $store.screens.find(screen => screen._id === $store.selectedScreenId) return $store.screens.find(
(screen) => screen._id === $store.selectedScreenId
)
} else if (type === FrontendTypes.LAYOUT) { } else if (type === FrontendTypes.LAYOUT) {
return $store.layouts.find(layout => layout._id === $store.selectedLayoutId) return $store.layouts.find(
(layout) => layout._id === $store.selectedLayoutId
)
} }
return null return null
}) })
@ -32,24 +36,24 @@ export const selectedComponent = derived(
} }
) )
export const currentAssetId = derived(store, $store => { export const currentAssetId = derived(store, ($store) => {
return $store.currentFrontEndType === FrontendTypes.SCREEN return $store.currentFrontEndType === FrontendTypes.SCREEN
? $store.selectedScreenId ? $store.selectedScreenId
: $store.selectedLayoutId : $store.selectedLayoutId
}) })
export const currentAssetName = derived(currentAsset, $currentAsset => { export const currentAssetName = derived(currentAsset, ($currentAsset) => {
return $currentAsset?.name return $currentAsset?.name
}) })
// leave this as before for consistency // leave this as before for consistency
export const allScreens = derived(store, $store => { export const allScreens = derived(store, ($store) => {
return $store.screens return $store.screens
}) })
export const mainLayout = derived(store, $store => { export const mainLayout = derived(store, ($store) => {
return $store.layouts?.find( return $store.layouts?.find(
layout => layout._id === LAYOUT_NAMES.MASTER.PRIVATE (layout) => layout._id === LAYOUT_NAMES.MASTER.PRIVATE
) )
}) })

View File

@ -5,7 +5,7 @@ import { get } from "builderStore/api"
* their props and other metadata from components.json. * their props and other metadata from components.json.
* @param {string} appId - ID of the currently running app * @param {string} appId - ID of the currently running app
*/ */
export const fetchComponentLibDefinitions = async appId => { export const fetchComponentLibDefinitions = async (appId) => {
const LIB_DEFINITION_URL = `/api/${appId}/components/definitions` const LIB_DEFINITION_URL = `/api/${appId}/components/definitions`
try { try {
const libDefinitionResponse = await get(LIB_DEFINITION_URL) const libDefinitionResponse = await get(LIB_DEFINITION_URL)

View File

@ -37,7 +37,7 @@ export default class Automation {
return return
} }
const stepIdx = steps.findIndex(step => step.id === id) const stepIdx = steps.findIndex((step) => step.id === id)
if (stepIdx < 0) throw new Error("Block not found.") if (stepIdx < 0) throw new Error("Block not found.")
steps.splice(stepIdx, 1, updatedBlock) steps.splice(stepIdx, 1, updatedBlock)
this.automation.definition.steps = steps this.automation.definition.steps = steps
@ -51,7 +51,7 @@ export default class Automation {
return return
} }
const stepIdx = steps.findIndex(step => step.id === id) const stepIdx = steps.findIndex((step) => step.id === id)
if (stepIdx < 0) throw new Error("Block not found.") if (stepIdx < 0) throw new Error("Block not found.")
steps.splice(stepIdx, 1) steps.splice(stepIdx, 1)
this.automation.definition.steps = steps this.automation.definition.steps = steps

View File

@ -4,14 +4,14 @@ import Automation from "./Automation"
import { cloneDeep } from "lodash/fp" import { cloneDeep } from "lodash/fp"
import analytics from "analytics" import analytics from "analytics"
const automationActions = store => ({ const automationActions = (store) => ({
fetch: async () => { fetch: async () => {
const responses = await Promise.all([ const responses = await Promise.all([
api.get(`/api/automations`), api.get(`/api/automations`),
api.get(`/api/automations/definitions/list`), api.get(`/api/automations/definitions/list`),
]) ])
const jsonResponses = await Promise.all(responses.map(x => x.json())) const jsonResponses = await Promise.all(responses.map((x) => x.json()))
store.update(state => { store.update((state) => {
let selected = state.selectedAutomation?.automation let selected = state.selectedAutomation?.automation
state.automations = jsonResponses[0] state.automations = jsonResponses[0]
state.blockDefinitions = { state.blockDefinitions = {
@ -22,7 +22,7 @@ const automationActions = store => ({
// if previously selected find the new obj and select it // if previously selected find the new obj and select it
if (selected) { if (selected) {
selected = jsonResponses[0].filter( selected = jsonResponses[0].filter(
automation => automation._id === selected._id (automation) => automation._id === selected._id
) )
state.selectedAutomation = new Automation(selected[0]) state.selectedAutomation = new Automation(selected[0])
} }
@ -40,7 +40,7 @@ const automationActions = store => ({
const CREATE_AUTOMATION_URL = `/api/automations` const CREATE_AUTOMATION_URL = `/api/automations`
const response = await api.post(CREATE_AUTOMATION_URL, automation) const response = await api.post(CREATE_AUTOMATION_URL, automation)
const json = await response.json() const json = await response.json()
store.update(state => { store.update((state) => {
state.automations = [...state.automations, json.automation] state.automations = [...state.automations, json.automation]
store.actions.select(json.automation) store.actions.select(json.automation)
return state return state
@ -50,9 +50,9 @@ const automationActions = store => ({
const UPDATE_AUTOMATION_URL = `/api/automations` const UPDATE_AUTOMATION_URL = `/api/automations`
const response = await api.put(UPDATE_AUTOMATION_URL, automation) const response = await api.put(UPDATE_AUTOMATION_URL, automation)
const json = await response.json() const json = await response.json()
store.update(state => { store.update((state) => {
const existingIdx = state.automations.findIndex( const existingIdx = state.automations.findIndex(
existing => existing._id === automation._id (existing) => existing._id === automation._id
) )
state.automations.splice(existingIdx, 1, json.automation) state.automations.splice(existingIdx, 1, json.automation)
state.automations = state.automations state.automations = state.automations
@ -65,9 +65,9 @@ const automationActions = store => ({
const DELETE_AUTOMATION_URL = `/api/automations/${_id}/${_rev}` const DELETE_AUTOMATION_URL = `/api/automations/${_id}/${_rev}`
await api.delete(DELETE_AUTOMATION_URL) await api.delete(DELETE_AUTOMATION_URL)
store.update(state => { store.update((state) => {
const existingIdx = state.automations.findIndex( const existingIdx = state.automations.findIndex(
existing => existing._id === _id (existing) => existing._id === _id
) )
state.automations.splice(existingIdx, 1) state.automations.splice(existingIdx, 1)
state.automations = state.automations state.automations = state.automations
@ -81,15 +81,15 @@ const automationActions = store => ({
const TRIGGER_AUTOMATION_URL = `/api/automations/${_id}/trigger` const TRIGGER_AUTOMATION_URL = `/api/automations/${_id}/trigger`
return await api.post(TRIGGER_AUTOMATION_URL) return await api.post(TRIGGER_AUTOMATION_URL)
}, },
select: automation => { select: (automation) => {
store.update(state => { store.update((state) => {
state.selectedAutomation = new Automation(cloneDeep(automation)) state.selectedAutomation = new Automation(cloneDeep(automation))
state.selectedBlock = null state.selectedBlock = null
return state return state
}) })
}, },
addBlockToAutomation: block => { addBlockToAutomation: (block) => {
store.update(state => { store.update((state) => {
const newBlock = state.selectedAutomation.addBlock(cloneDeep(block)) const newBlock = state.selectedAutomation.addBlock(cloneDeep(block))
state.selectedBlock = newBlock state.selectedBlock = newBlock
return state return state
@ -98,10 +98,10 @@ const automationActions = store => ({
name: block.name, name: block.name,
}) })
}, },
deleteAutomationBlock: block => { deleteAutomationBlock: (block) => {
store.update(state => { store.update((state) => {
const idx = state.selectedAutomation.automation.definition.steps.findIndex( const idx = state.selectedAutomation.automation.definition.steps.findIndex(
x => x.id === block.id (x) => x.id === block.id
) )
state.selectedAutomation.deleteBlock(block.id) state.selectedAutomation.deleteBlock(block.id)

View File

@ -49,10 +49,10 @@ export const getFrontendStore = () => {
const store = writable({ ...INITIAL_FRONTEND_STATE }) const store = writable({ ...INITIAL_FRONTEND_STATE })
store.actions = { store.actions = {
initialise: async pkg => { initialise: async (pkg) => {
const { layouts, screens, application, clientLibPath } = pkg const { layouts, screens, application, clientLibPath } = pkg
const components = await fetchComponentLibDefinitions(application._id) const components = await fetchComponentLibDefinitions(application._id)
store.update(state => ({ store.update((state) => ({
...state, ...state,
libraries: application.componentLibraries, libraries: application.componentLibraries,
components, components,
@ -70,7 +70,7 @@ export const getFrontendStore = () => {
// Initialise backend stores // Initialise backend stores
const [_integrations] = await Promise.all([ const [_integrations] = await Promise.all([
api.get("/api/integrations").then(r => r.json()), api.get("/api/integrations").then((r) => r.json()),
]) ])
datasources.init() datasources.init()
integrations.set(_integrations) integrations.set(_integrations)
@ -82,18 +82,18 @@ export const getFrontendStore = () => {
fetch: async () => { fetch: async () => {
const response = await api.get("/api/routing") const response = await api.get("/api/routing")
const json = await response.json() const json = await response.json()
store.update(state => { store.update((state) => {
state.routes = json.routes state.routes = json.routes
return state return state
}) })
}, },
}, },
screens: { screens: {
select: screenId => { select: (screenId) => {
store.update(state => { store.update((state) => {
let screens = get(allScreens) let screens = get(allScreens)
let screen = let screen =
screens.find(screen => screen._id === screenId) || screens[0] screens.find((screen) => screen._id === screenId) || screens[0]
if (!screen) return state if (!screen) return state
// Update role to the screen's role setting so that it will always // Update role to the screen's role setting so that it will always
@ -107,9 +107,9 @@ export const getFrontendStore = () => {
return state return state
}) })
}, },
create: async screen => { create: async (screen) => {
screen = await store.actions.screens.save(screen) screen = await store.actions.screens.save(screen)
store.update(state => { store.update((state) => {
state.selectedScreenId = screen._id state.selectedScreenId = screen._id
state.selectedComponentId = screen.props._id state.selectedComponentId = screen.props._id
state.currentFrontEndType = FrontendTypes.SCREEN state.currentFrontEndType = FrontendTypes.SCREEN
@ -118,15 +118,15 @@ export const getFrontendStore = () => {
}) })
return screen return screen
}, },
save: async screen => { save: async (screen) => {
const creatingNewScreen = screen._id === undefined const creatingNewScreen = screen._id === undefined
const response = await api.post(`/api/screens`, screen) const response = await api.post(`/api/screens`, screen)
screen = await response.json() screen = await response.json()
await store.actions.routing.fetch() await store.actions.routing.fetch()
store.update(state => { store.update((state) => {
const foundScreen = state.screens.findIndex( const foundScreen = state.screens.findIndex(
el => el._id === screen._id (el) => el._id === screen._id
) )
if (foundScreen !== -1) { if (foundScreen !== -1) {
state.screens.splice(foundScreen, 1) state.screens.splice(foundScreen, 1)
@ -141,14 +141,14 @@ export const getFrontendStore = () => {
return screen return screen
}, },
delete: async screens => { delete: async (screens) => {
const screensToDelete = Array.isArray(screens) ? screens : [screens] const screensToDelete = Array.isArray(screens) ? screens : [screens]
const screenDeletePromises = [] const screenDeletePromises = []
store.update(state => { store.update((state) => {
for (let screenToDelete of screensToDelete) { for (let screenToDelete of screensToDelete) {
state.screens = state.screens.filter( state.screens = state.screens.filter(
screen => screen._id !== screenToDelete._id (screen) => screen._id !== screenToDelete._id
) )
screenDeletePromises.push( screenDeletePromises.push(
api.delete( api.delete(
@ -177,8 +177,8 @@ export const getFrontendStore = () => {
}, },
}, },
layouts: { layouts: {
select: layoutId => { select: (layoutId) => {
store.update(state => { store.update((state) => {
const layout = const layout =
store.actions.layouts.find(layoutId) || get(store).layouts[0] store.actions.layouts.find(layoutId) || get(store).layouts[0]
if (!layout) return if (!layout) return
@ -189,15 +189,15 @@ export const getFrontendStore = () => {
return state return state
}) })
}, },
save: async layout => { save: async (layout) => {
const layoutToSave = cloneDeep(layout) const layoutToSave = cloneDeep(layout)
const creatingNewLayout = layoutToSave._id === undefined const creatingNewLayout = layoutToSave._id === undefined
const response = await api.post(`/api/layouts`, layoutToSave) const response = await api.post(`/api/layouts`, layoutToSave)
const savedLayout = await response.json() const savedLayout = await response.json()
store.update(state => { store.update((state) => {
const layoutIdx = state.layouts.findIndex( const layoutIdx = state.layouts.findIndex(
stateLayout => stateLayout._id === savedLayout._id (stateLayout) => stateLayout._id === savedLayout._id
) )
if (layoutIdx >= 0) { if (layoutIdx >= 0) {
// update existing layout // update existing layout
@ -216,14 +216,14 @@ export const getFrontendStore = () => {
return savedLayout return savedLayout
}, },
find: layoutId => { find: (layoutId) => {
if (!layoutId) { if (!layoutId) {
return get(mainLayout) return get(mainLayout)
} }
const storeContents = get(store) const storeContents = get(store)
return storeContents.layouts.find(layout => layout._id === layoutId) return storeContents.layouts.find((layout) => layout._id === layoutId)
}, },
delete: async layoutToDelete => { delete: async (layoutToDelete) => {
const response = await api.delete( const response = await api.delete(
`/api/layouts/${layoutToDelete._id}/${layoutToDelete._rev}` `/api/layouts/${layoutToDelete._id}/${layoutToDelete._rev}`
) )
@ -231,9 +231,9 @@ export const getFrontendStore = () => {
const json = await response.json() const json = await response.json()
throw new Error(json.message) throw new Error(json.message)
} }
store.update(state => { store.update((state) => {
state.layouts = state.layouts.filter( state.layouts = state.layouts.filter(
layout => layout._id !== layoutToDelete._id (layout) => layout._id !== layoutToDelete._id
) )
if (layoutToDelete._id === state.selectedLayoutId) { if (layoutToDelete._id === state.selectedLayoutId) {
state.selectedLayoutId = get(mainLayout)._id state.selectedLayoutId = get(mainLayout)._id
@ -243,7 +243,7 @@ export const getFrontendStore = () => {
}, },
}, },
components: { components: {
select: component => { select: (component) => {
if (!component) { if (!component) {
return return
} }
@ -263,13 +263,13 @@ export const getFrontendStore = () => {
} }
// Otherwise select the component // Otherwise select the component
store.update(state => { store.update((state) => {
state.selectedComponentId = component._id state.selectedComponentId = component._id
state.currentView = "component" state.currentView = "component"
return state return state
}) })
}, },
getDefinition: componentName => { getDefinition: (componentName) => {
if (!componentName) { if (!componentName) {
return null return null
} }
@ -287,7 +287,7 @@ export const getFrontendStore = () => {
// Generate default props // Generate default props
let props = { ...presetProps } let props = { ...presetProps }
if (definition.settings) { if (definition.settings) {
definition.settings.forEach(setting => { definition.settings.forEach((setting) => {
if (setting.defaultValue !== undefined) { if (setting.defaultValue !== undefined) {
props[setting.key] = setting.defaultValue props[setting.key] = setting.defaultValue
} }
@ -367,7 +367,7 @@ export const getFrontendStore = () => {
// Save components and update UI // Save components and update UI
await store.actions.preview.saveSelected() await store.actions.preview.saveSelected()
store.update(state => { store.update((state) => {
state.currentView = "component" state.currentView = "component"
state.selectedComponentId = componentInstance._id state.selectedComponentId = componentInstance._id
return state return state
@ -380,7 +380,7 @@ export const getFrontendStore = () => {
return componentInstance return componentInstance
}, },
delete: async component => { delete: async (component) => {
if (!component) { if (!component) {
return return
} }
@ -391,7 +391,7 @@ export const getFrontendStore = () => {
const parent = findComponentParent(asset.props, component._id) const parent = findComponentParent(asset.props, component._id)
if (parent) { if (parent) {
parent._children = parent._children.filter( parent._children = parent._children.filter(
child => child._id !== component._id (child) => child._id !== component._id
) )
store.actions.components.select(parent) store.actions.components.select(parent)
} }
@ -404,7 +404,7 @@ export const getFrontendStore = () => {
} }
// Update store with copied component // Update store with copied component
store.update(state => { store.update((state) => {
state.componentToPaste = cloneDeep(component) state.componentToPaste = cloneDeep(component)
state.componentToPaste.isCut = cut state.componentToPaste.isCut = cut
return state return state
@ -415,7 +415,7 @@ export const getFrontendStore = () => {
const parent = findComponentParent(selectedAsset.props, component._id) const parent = findComponentParent(selectedAsset.props, component._id)
if (parent) { if (parent) {
parent._children = parent._children.filter( parent._children = parent._children.filter(
child => child._id !== component._id (child) => child._id !== component._id
) )
store.actions.components.select(parent) store.actions.components.select(parent)
} }
@ -423,7 +423,7 @@ export const getFrontendStore = () => {
}, },
paste: async (targetComponent, mode) => { paste: async (targetComponent, mode) => {
let promises = [] let promises = []
store.update(state => { store.update((state) => {
// Stop if we have nothing to paste // Stop if we have nothing to paste
if (!state.componentToPaste) { if (!state.componentToPaste) {
return state return state
@ -444,7 +444,7 @@ export const getFrontendStore = () => {
if (cut) { if (cut) {
state.componentToPaste = null state.componentToPaste = null
} else { } else {
const randomizeIds = component => { const randomizeIds = (component) => {
if (!component) { if (!component) {
return return
} }
@ -497,7 +497,7 @@ export const getFrontendStore = () => {
} }
await store.actions.preview.saveSelected() await store.actions.preview.saveSelected()
}, },
updateCustomStyle: async style => { updateCustomStyle: async (style) => {
const selected = get(selectedComponent) const selected = get(selectedComponent)
selected._styles.custom = style selected._styles.custom = style
await store.actions.preview.saveSelected() await store.actions.preview.saveSelected()
@ -507,7 +507,7 @@ export const getFrontendStore = () => {
selected._styles = { normal: {}, hover: {}, active: {} } selected._styles = { normal: {}, hover: {}, active: {} }
await store.actions.preview.saveSelected() await store.actions.preview.saveSelected()
}, },
updateTransition: async transition => { updateTransition: async (transition) => {
const selected = get(selectedComponent) const selected = get(selectedComponent)
if (transition == null || transition === "") { if (transition == null || transition === "") {
selected._transition = "" selected._transition = ""
@ -522,7 +522,7 @@ export const getFrontendStore = () => {
return return
} }
component[name] = value component[name] = value
store.update(state => { store.update((state) => {
state.selectedComponentId = component._id state.selectedComponentId = component._id
return state return state
}) })

View File

@ -17,18 +17,20 @@ export const getHostingStore = () => {
api.get("/api/hosting/"), api.get("/api/hosting/"),
api.get("/api/hosting/urls"), api.get("/api/hosting/urls"),
]) ])
const [info, urls] = await Promise.all(responses.map(resp => resp.json())) const [info, urls] = await Promise.all(
store.update(state => { responses.map((resp) => resp.json())
)
store.update((state) => {
state.hostingInfo = info state.hostingInfo = info
state.appUrl = urls.app state.appUrl = urls.app
return state return state
}) })
return info return info
}, },
save: async hostingInfo => { save: async (hostingInfo) => {
const response = await api.post("/api/hosting", hostingInfo) const response = await api.post("/api/hosting", hostingInfo)
const revision = (await response.json()).rev const revision = (await response.json()).rev
store.update(state => { store.update((state) => {
state.hostingInfo = { state.hostingInfo = {
...hostingInfo, ...hostingInfo,
_rev: revision, _rev: revision,
@ -38,10 +40,12 @@ export const getHostingStore = () => {
}, },
fetchDeployedApps: async () => { fetchDeployedApps: async () => {
let deployments = await (await get("/api/hosting/apps")).json() let deployments = await (await get("/api/hosting/apps")).json()
store.update(state => { store.update((state) => {
state.deployedApps = deployments state.deployedApps = deployments
state.deployedAppNames = Object.values(deployments).map(app => app.name) state.deployedAppNames = Object.values(deployments).map(
state.deployedAppUrls = Object.values(deployments).map(app => app.url) (app) => app.name
)
state.deployedAppUrls = Object.values(deployments).map((app) => app.url)
return state return state
}) })
return deployments return deployments

View File

@ -12,13 +12,13 @@ export const localStorageStore = (localStorageKey, initialValue) => {
}) })
// New store setter which updates the store and localstorage // New store setter which updates the store and localstorage
const set = value => { const set = (value) => {
store.set(value) store.set(value)
localStorage.setItem(localStorageKey, JSON.stringify(value)) localStorage.setItem(localStorageKey, JSON.stringify(value))
} }
// New store updater which updates the store and localstorage // New store updater which updates the store and localstorage
const update = updaterFn => set(updaterFn(get(store))) const update = (updaterFn) => set(updaterFn(get(store)))
// Hydrates the store from localstorage // Hydrates the store from localstorage
const hydrate = () => { const hydrate = () => {

View File

@ -6,7 +6,7 @@ export const notificationStore = writable({
}) })
export function send(message, type = "default") { export function send(message, type = "default") {
notificationStore.update(state => { notificationStore.update((state) => {
state.notifications = [ state.notifications = [
...state.notifications, ...state.notifications,
{ id: generate(), type, message }, { id: generate(), type, message },
@ -16,8 +16,8 @@ export function send(message, type = "default") {
} }
export const notifier = { export const notifier = {
danger: msg => send(msg, "danger"), danger: (msg) => send(msg, "danger"),
warning: msg => send(msg, "warning"), warning: (msg) => send(msg, "warning"),
info: msg => send(msg, "info"), info: (msg) => send(msg, "info"),
success: msg => send(msg, "success"), success: (msg) => send(msg, "success"),
} }

View File

@ -3,7 +3,7 @@ import rowDetailScreen from "./rowDetailScreen"
import rowListScreen from "./rowListScreen" import rowListScreen from "./rowListScreen"
import createFromScratchScreen from "./createFromScratchScreen" import createFromScratchScreen from "./createFromScratchScreen"
const allTemplates = tables => [ const allTemplates = (tables) => [
...newRowScreen(tables), ...newRowScreen(tables),
...rowDetailScreen(tables), ...rowDetailScreen(tables),
...rowListScreen(tables), ...rowListScreen(tables),
@ -18,7 +18,7 @@ const createTemplateOverride = (frontendState, create) => () => {
} }
export default (frontendState, tables) => { export default (frontendState, tables) => {
const enrichTemplate = template => ({ const enrichTemplate = (template) => ({
...template, ...template,
create: createTemplateOverride(frontendState, template.create), create: createTemplateOverride(frontendState, template.create),
}) })

View File

@ -9,8 +9,8 @@ import {
makeDatasourceFormComponents, makeDatasourceFormComponents,
} from "./utils/commonComponents" } from "./utils/commonComponents"
export default function(tables) { export default function (tables) {
return tables.map(table => { return tables.map((table) => {
return { return {
name: `${table.name} - New`, name: `${table.name} - New`,
create: () => createScreen(table), create: () => createScreen(table),
@ -19,14 +19,14 @@ export default function(tables) {
}) })
} }
export const newRowUrl = table => sanitizeUrl(`/${table.name}/new/row`) export const newRowUrl = (table) => sanitizeUrl(`/${table.name}/new/row`)
export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE" export const NEW_ROW_TEMPLATE = "NEW_ROW_TEMPLATE"
function generateTitleContainer(table, formId) { function generateTitleContainer(table, formId) {
return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId)) return makeTitleContainer("New Row").addChild(makeSaveButton(table, formId))
} }
const createScreen = table => { const createScreen = (table) => {
const screen = new Screen() const screen = new Screen()
.component("@budibase/standard-components/container") .component("@budibase/standard-components/container")
.instanceName(`${table.name} - New`) .instanceName(`${table.name} - New`)
@ -52,7 +52,7 @@ const createScreen = table => {
// Add all form fields from this schema to the field group // Add all form fields from this schema to the field group
const datasource = { type: "table", tableId: table._id } const datasource = { type: "table", tableId: table._id }
makeDatasourceFormComponents(datasource).forEach(component => { makeDatasourceFormComponents(datasource).forEach((component) => {
fieldGroup.addChild(component) fieldGroup.addChild(component)
}) })

View File

@ -12,8 +12,8 @@ import {
makeDatasourceFormComponents, makeDatasourceFormComponents,
} from "./utils/commonComponents" } from "./utils/commonComponents"
export default function(tables) { export default function (tables) {
return tables.map(table => { return tables.map((table) => {
return { return {
name: `${table.name} - Detail`, name: `${table.name} - Detail`,
create: () => createScreen(table), create: () => createScreen(table),
@ -23,7 +23,7 @@ export default function(tables) {
} }
export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE" export const ROW_DETAIL_TEMPLATE = "ROW_DETAIL_TEMPLATE"
export const rowDetailUrl = table => sanitizeUrl(`/${table.name}/:id`) export const rowDetailUrl = (table) => sanitizeUrl(`/${table.name}/:id`)
function generateTitleContainer(table, title, formId, repeaterId) { function generateTitleContainer(table, title, formId, repeaterId) {
// have to override style for this, its missing margin // have to override style for this, its missing margin
@ -77,12 +77,10 @@ function generateTitleContainer(table, title, formId, repeaterId) {
}) })
.instanceName("Delete Button") .instanceName("Delete Button")
return makeTitleContainer(title) return makeTitleContainer(title).addChild(deleteButton).addChild(saveButton)
.addChild(deleteButton)
.addChild(saveButton)
} }
const createScreen = table => { const createScreen = (table) => {
const provider = new Component("@budibase/standard-components/dataprovider") const provider = new Component("@budibase/standard-components/dataprovider")
.instanceName(`Data Provider`) .instanceName(`Data Provider`)
.customProps({ .customProps({
@ -124,7 +122,7 @@ const createScreen = table => {
// Add all form fields from this schema to the field group // Add all form fields from this schema to the field group
const datasource = { type: "table", tableId: table._id } const datasource = { type: "table", tableId: table._id }
makeDatasourceFormComponents(datasource).forEach(component => { makeDatasourceFormComponents(datasource).forEach((component) => {
fieldGroup.addChild(component) fieldGroup.addChild(component)
}) })

View File

@ -4,8 +4,8 @@ import { Screen } from "./utils/Screen"
import { Component } from "./utils/Component" import { Component } from "./utils/Component"
import { makePropSafe } from "@budibase/string-templates" import { makePropSafe } from "@budibase/string-templates"
export default function(tables) { export default function (tables) {
return tables.map(table => { return tables.map((table) => {
return { return {
name: `${table.name} - List`, name: `${table.name} - List`,
create: () => createScreen(table), create: () => createScreen(table),
@ -15,7 +15,7 @@ export default function(tables) {
} }
export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE" export const ROW_LIST_TEMPLATE = "ROW_LIST_TEMPLATE"
export const rowListUrl = table => sanitizeUrl(`/${table.name}`) export const rowListUrl = (table) => sanitizeUrl(`/${table.name}`)
function generateTitleContainer(table) { function generateTitleContainer(table) {
const newButton = new Component("@budibase/standard-components/button") const newButton = new Component("@budibase/standard-components/button")
@ -70,7 +70,7 @@ function generateTitleContainer(table) {
.addChild(newButton) .addChild(newButton)
} }
const createScreen = table => { const createScreen = (table) => {
const provider = new Component("@budibase/standard-components/dataprovider") const provider = new Component("@budibase/standard-components/dataprovider")
.instanceName(`Data Provider`) .instanceName(`Data Provider`)
.customProps({ .customProps({

View File

@ -178,7 +178,7 @@ export function makeDatasourceFormComponents(datasource) {
const { schema } = getSchemaForDatasource(datasource, true) const { schema } = getSchemaForDatasource(datasource, true)
let components = [] let components = []
let fields = Object.keys(schema || {}) let fields = Object.keys(schema || {})
fields.forEach(field => { fields.forEach((field) => {
const fieldSchema = schema[field] const fieldSchema = schema[field]
// skip autocolumns // skip autocolumns
if (fieldSchema.autocolumn) { if (fieldSchema.autocolumn) {

View File

@ -1,7 +1,7 @@
export default function(url) { export default function (url) {
return url return url
.split("/") .split("/")
.map(part => { .map((part) => {
// if parameter, then use as is // if parameter, then use as is
if (part.startsWith(":")) return part if (part.startsWith(":")) return part
return encodeURIComponent(part.replace(/ /g, "-")) return encodeURIComponent(part.replace(/ /g, "-"))

View File

@ -9,14 +9,14 @@ export const getThemeStore = () => {
const store = localStorageStore("bb-theme", initialValue) const store = localStorageStore("bb-theme", initialValue)
// Update theme class when store changes // Update theme class when store changes
store.subscribe(state => { store.subscribe((state) => {
// Handle any old local storage values - this can be removed after the update // Handle any old local storage values - this can be removed after the update
if (state.darkMode !== undefined) { if (state.darkMode !== undefined) {
store.set(initialValue) store.set(initialValue)
return return
} }
state.options.forEach(option => { state.options.forEach((option) => {
themeElement.classList.toggle( themeElement.classList.toggle(
`spectrum--${option}`, `spectrum--${option}`,
option === state.theme option === state.theme

View File

@ -2,14 +2,14 @@
* Recursively searches for a specific component ID * Recursively searches for a specific component ID
*/ */
export const findComponent = (rootComponent, id) => { export const findComponent = (rootComponent, id) => {
return searchComponentTree(rootComponent, comp => comp._id === id) return searchComponentTree(rootComponent, (comp) => comp._id === id)
} }
/** /**
* Recursively searches for a specific component type * Recursively searches for a specific component type
*/ */
export const findComponentType = (rootComponent, type) => { export const findComponentType = (rootComponent, type) => {
return searchComponentTree(rootComponent, comp => comp._component === type) return searchComponentTree(rootComponent, (comp) => comp._component === type)
} }
/** /**
@ -68,7 +68,7 @@ export const findAllMatchingComponents = (rootComponent, selector) => {
} }
let components = [] let components = []
if (rootComponent._children) { if (rootComponent._children) {
rootComponent._children.forEach(child => { rootComponent._children.forEach((child) => {
components = [ components = [
...components, ...components,
...findAllMatchingComponents(child, selector), ...findAllMatchingComponents(child, selector),

View File

@ -1,7 +1,7 @@
export function uuid() { export function uuid() {
// always want to make this start with a letter, as this makes it // always want to make this start with a letter, as this makes it
// easier to use with template string bindings in the client // easier to use with template string bindings in the client
return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, c => { return "cxxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx".replace(/[xy]/g, (c) => {
const r = (Math.random() * 16) | 0, const r = (Math.random() * 16) | 0,
v = c == "x" ? r : (r & 0x3) | 0x8 v = c == "x" ? r : (r & 0x3) | 0x8
return v.toString(16) return v.toString(16)

View File

@ -13,12 +13,12 @@ export const DropPosition = {
INSIDE: "inside", INSIDE: "inside",
} }
export default function() { export default function () {
const store = writable({}) const store = writable({})
store.actions = { store.actions = {
dragstart: component => { dragstart: (component) => {
store.update(state => { store.update((state) => {
state.dragged = component state.dragged = component
return state return state
}) })
@ -29,7 +29,7 @@ export default function() {
canHaveChildrenButIsEmpty, canHaveChildrenButIsEmpty,
mousePosition, mousePosition,
}) => { }) => {
store.update(state => { store.update((state) => {
state.targetComponent = component state.targetComponent = component
// only allow dropping inside when container is empty // only allow dropping inside when container is empty
// if container has children, drag over them // if container has children, drag over them
@ -65,7 +65,7 @@ export default function() {
}) })
}, },
reset: () => { reset: () => {
store.update(state => { store.update((state) => {
state.dropPosition = "" state.dropPosition = ""
state.targetComponent = null state.targetComponent = null
state.dragged = null state.dragged = null
@ -85,7 +85,7 @@ export default function() {
} }
// Stop if the target is a child of source // Stop if the target is a child of source
const path = findComponentPath(state.dragged, state.targetComponent._id) const path = findComponentPath(state.dragged, state.targetComponent._id)
const ids = path.map(component => component._id) const ids = path.map((component) => component._id)
if (ids.includes(state.targetComponent._id)) { if (ids.includes(state.targetComponent._id)) {
return return
} }

View File

@ -3,7 +3,7 @@ import { getManifest } from "@budibase/string-templates"
export function handlebarsCompletions() { export function handlebarsCompletions() {
const manifest = getManifest() const manifest = getManifest()
return Object.keys(manifest).flatMap(key => return Object.keys(manifest).flatMap((key) =>
Object.entries(manifest[key]).map(([helperName, helperConfig]) => ({ Object.entries(manifest[key]).map(([helperName, helperConfig]) => ({
text: helperName, text: helperName,
path: helperName, path: helperName,

View File

@ -1,6 +1,6 @@
import { last, flow } from "lodash/fp" import { last, flow } from "lodash/fp"
export const buildStyle = styles => { export const buildStyle = (styles) => {
let str = "" let str = ""
for (let s in styles) { for (let s in styles) {
if (styles[s]) { if (styles[s]) {
@ -11,14 +11,15 @@ export const buildStyle = styles => {
return str return str
} }
export const convertCamel = str => { export const convertCamel = (str) => {
return str.replace(/[A-Z]/g, match => `-${match.toLowerCase()}`) return str.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`)
} }
export const pipe = (arg, funcs) => flow(funcs)(arg) export const pipe = (arg, funcs) => flow(funcs)(arg)
export const capitalise = s => s.substring(0, 1).toUpperCase() + s.substring(1) export const capitalise = (s) =>
s.substring(0, 1).toUpperCase() + s.substring(1)
export const get_name = s => (!s ? "" : last(s.split("/"))) export const get_name = (s) => (!s ? "" : last(s.split("/")))
export const get_capitalised_name = name => pipe(name, [get_name, capitalise]) export const get_capitalised_name = (name) => pipe(name, [get_name, capitalise])

View File

@ -13,12 +13,12 @@ export function createAuthStore() {
const { subscribe, set } = writable(null) const { subscribe, set } = writable(null)
checkAuth() checkAuth()
.then(user => set({ user })) .then((user) => set({ user }))
.catch(() => set({ user: null })) .catch(() => set({ user: null }))
return { return {
subscribe, subscribe,
login: async creds => { login: async (creds) => {
const response = await api.post(`/api/admin/auth`, creds) const response = await api.post(`/api/admin/auth`, creds)
const json = await response.json() const json = await response.json()
if (response.status === 200) { if (response.status === 200) {
@ -36,7 +36,7 @@ export function createAuthStore() {
await response.json() await response.json()
set({ user: null }) set({ user: null })
}, },
createUser: async user => { createUser: async (user) => {
const response = await api.post(`/api/admin/users`, user) const response = await api.post(`/api/admin/users`, user)
if (response.status !== 200) { if (response.status !== 200) {
throw "Unable to create user" throw "Unable to create user"

View File

@ -21,19 +21,19 @@ export function createDatasourcesStore() {
fetch: async () => { fetch: async () => {
const response = await api.get(`/api/datasources`) const response = await api.get(`/api/datasources`)
const json = await response.json() const json = await response.json()
update(state => ({ ...state, list: json })) update((state) => ({ ...state, list: json }))
return json return json
}, },
select: async datasourceId => { select: async (datasourceId) => {
update(state => ({ ...state, selected: datasourceId })) update((state) => ({ ...state, selected: datasourceId }))
queries.update(state => ({ ...state, selected: null })) queries.update((state) => ({ ...state, selected: null }))
}, },
save: async datasource => { save: async (datasource) => {
const response = await api.post("/api/datasources", datasource) const response = await api.post("/api/datasources", datasource)
const json = await response.json() const json = await response.json()
update(state => { update((state) => {
const currentIdx = state.list.findIndex(ds => ds._id === json._id) const currentIdx = state.list.findIndex((ds) => ds._id === json._id)
const sources = state.list const sources = state.list
@ -47,13 +47,13 @@ export function createDatasourcesStore() {
}) })
return json return json
}, },
delete: async datasource => { delete: async (datasource) => {
const response = await api.delete( const response = await api.delete(
`/api/datasources/${datasource._id}/${datasource._rev}` `/api/datasources/${datasource._id}/${datasource._rev}`
) )
update(state => { update((state) => {
const sources = state.list.filter( const sources = state.list.filter(
existing => existing._id !== datasource._id (existing) => existing._id !== datasource._id
) )
return { list: sources, selected: null } return { list: sources, selected: null }
}) })

View File

@ -6,7 +6,7 @@ export function createPermissionStore() {
return { return {
subscribe, subscribe,
forResource: async resourceId => { forResource: async (resourceId) => {
const response = await api.get(`/api/permission/${resourceId}`) const response = await api.get(`/api/permission/${resourceId}`)
const json = await response.json() const json = await response.json()
return json return json

View File

@ -17,13 +17,13 @@ export function createQueriesStore() {
fetch: async () => { fetch: async () => {
const response = await api.get(`/api/queries`) const response = await api.get(`/api/queries`)
const json = await response.json() const json = await response.json()
update(state => ({ ...state, list: json })) update((state) => ({ ...state, list: json }))
return json return json
}, },
save: async (datasourceId, query) => { save: async (datasourceId, query) => {
const _integrations = get(integrations) const _integrations = get(integrations)
const dataSource = get(datasources).list.filter( const dataSource = get(datasources).list.filter(
ds => ds._id === datasourceId (ds) => ds._id === datasourceId
) )
// check if readable attribute is found // check if readable attribute is found
if (dataSource.length !== 0) { if (dataSource.length !== 0) {
@ -39,8 +39,10 @@ export function createQueriesStore() {
throw new Error("Failed saving query.") throw new Error("Failed saving query.")
} }
const json = await response.json() const json = await response.json()
update(state => { update((state) => {
const currentIdx = state.list.findIndex(query => query._id === json._id) const currentIdx = state.list.findIndex(
(query) => query._id === json._id
)
const queries = state.list const queries = state.list
@ -53,16 +55,19 @@ export function createQueriesStore() {
}) })
return json return json
}, },
select: query => { select: (query) => {
update(state => ({ ...state, selected: query._id })) update((state) => ({ ...state, selected: query._id }))
datasources.update(state => ({ ...state, selected: query.datasourceId })) datasources.update((state) => ({
...state,
selected: query.datasourceId,
}))
}, },
delete: async query => { delete: async (query) => {
const response = await api.delete( const response = await api.delete(
`/api/queries/${query._id}/${query._rev}` `/api/queries/${query._id}/${query._rev}`
) )
update(state => { update((state) => {
state.list = state.list.filter(existing => existing._id !== query._id) state.list = state.list.filter((existing) => existing._id !== query._id)
if (state.selected === query._id) { if (state.selected === query._id) {
state.selected = null state.selected = null
} }

View File

@ -9,12 +9,12 @@ export function createRolesStore() {
fetch: async () => { fetch: async () => {
set(await getRoles()) set(await getRoles())
}, },
delete: async role => { delete: async (role) => {
const response = await api.delete(`/api/roles/${role._id}/${role._rev}`) const response = await api.delete(`/api/roles/${role._id}/${role._rev}`)
update(state => state.filter(existing => existing._id !== role._id)) update((state) => state.filter((existing) => existing._id !== role._id))
return response return response
}, },
save: async role => { save: async (role) => {
const response = await api.post("/api/roles", role) const response = await api.post("/api/roles", role)
set(await getRoles()) set(await getRoles())
return response return response

View File

@ -10,17 +10,17 @@ export function createTablesStore() {
async function fetch() { async function fetch() {
const tablesResponse = await api.get(`/api/tables`) const tablesResponse = await api.get(`/api/tables`)
const tables = await tablesResponse.json() const tables = await tablesResponse.json()
update(state => ({ ...state, list: tables })) update((state) => ({ ...state, list: tables }))
} }
async function select(table) { async function select(table) {
if (!table) { if (!table) {
update(state => ({ update((state) => ({
...state, ...state,
selected: {}, selected: {},
})) }))
} else { } else {
update(state => ({ update((state) => ({
...state, ...state,
selected: table, selected: table,
draft: cloneDeep(table), draft: cloneDeep(table),
@ -31,7 +31,7 @@ export function createTablesStore() {
async function save(table) { async function save(table) {
const updatedTable = cloneDeep(table) const updatedTable = cloneDeep(table)
const oldTable = get(store).list.filter(t => t._id === table._id)[0] const oldTable = get(store).list.filter((t) => t._id === table._id)[0]
const fieldNames = [] const fieldNames = []
// update any renamed schema keys to reflect their names // update any renamed schema keys to reflect their names
@ -78,16 +78,16 @@ export function createTablesStore() {
draft: {}, draft: {},
}) })
}, },
delete: async table => { delete: async (table) => {
await api.delete(`/api/tables/${table._id}/${table._rev}`) await api.delete(`/api/tables/${table._id}/${table._rev}`)
update(state => ({ update((state) => ({
...state, ...state,
list: state.list.filter(existing => existing._id !== table._id), list: state.list.filter((existing) => existing._id !== table._id),
selected: {}, selected: {},
})) }))
}, },
saveField: ({ originalName, field, primaryDisplay = false, indexes }) => { saveField: ({ originalName, field, primaryDisplay = false, indexes }) => {
update(state => { update((state) => {
// delete the original if renaming // delete the original if renaming
// need to handle if the column had no name, empty string // need to handle if the column had no name, empty string
if (originalName || originalName === "") { if (originalName || originalName === "") {
@ -115,8 +115,8 @@ export function createTablesStore() {
return state return state
}) })
}, },
deleteField: field => { deleteField: (field) => {
update(state => { update((state) => {
delete state.draft.schema[field.name] delete state.draft.schema[field.name]
save(state.draft) save(state.draft)
return state return state

View File

@ -10,17 +10,17 @@ export function createViewsStore() {
return { return {
subscribe, subscribe,
select: async view => { select: async (view) => {
update(state => ({ update((state) => ({
...state, ...state,
selected: view, selected: view,
})) }))
}, },
delete: async view => { delete: async (view) => {
await api.delete(`/api/views/${view}`) await api.delete(`/api/views/${view}`)
await tables.fetch() await tables.fetch()
}, },
save: async view => { save: async (view) => {
const response = await api.post(`/api/views`, view) const response = await api.post(`/api/views`, view)
const json = await response.json() const json = await response.json()
@ -30,14 +30,14 @@ export function createViewsStore() {
} }
const viewTable = get(tables).list.find( const viewTable = get(tables).list.find(
table => table._id === view.tableId (table) => table._id === view.tableId
) )
if (view.originalName) delete viewTable.views[view.originalName] if (view.originalName) delete viewTable.views[view.originalName]
viewTable.views[view.name] = viewMeta viewTable.views[view.name] = viewMeta
await tables.save(viewTable) await tables.save(viewTable)
update(state => ({ ...state, selected: viewMeta })) update((state) => ({ ...state, selected: viewMeta }))
}, },
} }
} }

View File

@ -61,7 +61,7 @@ module.exports.make = async (inputs = {}) => {
) )
} }
module.exports.get = property => { module.exports.get = (property) => {
const props = fs.readFileSync(FILE_PATH, "utf8").split(property) const props = fs.readFileSync(FILE_PATH, "utf8").split(property)
if (props[0].charAt(0) === "=") { if (props[0].charAt(0) === "=") {
property = props[0] property = props[0]

View File

@ -17,6 +17,6 @@ async function init() {
await program.parseAsync(process.argv) await program.parseAsync(process.argv)
} }
init().catch(err => { init().catch((err) => {
console.error(`Unexpected error - `, err) console.error(`Unexpected error - `, err)
}) })

View File

@ -1,6 +1,6 @@
const inquirer = require("inquirer") const inquirer = require("inquirer")
exports.confirmation = async question => { exports.confirmation = async (question) => {
const config = { const config = {
type: "confirm", type: "confirm",
message: question, message: question,
@ -27,7 +27,7 @@ exports.number = async (question, defaultNumber) => {
type: "input", type: "input",
name: "number", name: "number",
message: question, message: question,
validate: value => { validate: (value) => {
let valid = !isNaN(parseFloat(value)) let valid = !isNaN(parseFloat(value))
return valid || "Please enter a number" return valid || "Please enter a number"
}, },

View File

@ -34,7 +34,7 @@ class Command {
"--help", "--help",
getSubHelpDescription(`Get help with ${this.command} options`) getSubHelpDescription(`Get help with ${this.command} options`)
) )
command.action(async options => { command.action(async (options) => {
try { try {
let executed = false let executed = false
for (let opt of thisCmd.opts) { for (let opt of thisCmd.opts) {

View File

@ -21,23 +21,23 @@ exports.downloadFile = async (url, filePath) => {
}) })
} }
exports.getHelpDescription = string => { exports.getHelpDescription = (string) => {
return chalk.cyan(string) return chalk.cyan(string)
} }
exports.getSubHelpDescription = string => { exports.getSubHelpDescription = (string) => {
return chalk.green(string) return chalk.green(string)
} }
exports.error = error => { exports.error = (error) => {
return chalk.red(`Error - ${error}`) return chalk.red(`Error - ${error}`)
} }
exports.success = success => { exports.success = (success) => {
return chalk.green(success) return chalk.green(success)
} }
exports.info = info => { exports.info = (info) => {
return chalk.cyan(info) return chalk.cyan(info)
} }
@ -45,7 +45,7 @@ exports.logErrorToFile = (file, error) => {
fs.writeFileSync(path.resolve(`./${file}`), `Budibase Error\n${error}`) fs.writeFileSync(path.resolve(`./${file}`), `Budibase Error\n${error}`)
} }
exports.parseEnv = env => { exports.parseEnv = (env) => {
const lines = env.toString().split("\n") const lines = env.toString().split("\n")
let result = {} let result = {}
for (const line of lines) { for (const line of lines) {

View File

@ -7,7 +7,7 @@ let cache = {}
/** /**
* Handler for API errors. * Handler for API errors.
*/ */
const handleError = error => { const handleError = (error) => {
return { error } return { error }
} }
@ -61,7 +61,7 @@ const makeApiCall = async ({ method, url, body, json = true }) => {
* Future invocation for this URL will return the cached result instead of * Future invocation for this URL will return the cached result instead of
* hitting the server again. * hitting the server again.
*/ */
const makeCachedApiCall = async params => { const makeCachedApiCall = async (params) => {
const identifier = params.url const identifier = params.url
if (!identifier) { if (!identifier) {
return null return null
@ -76,7 +76,7 @@ const makeCachedApiCall = async params => {
/** /**
* Constructs an API call function for a particular HTTP method. * Constructs an API call function for a particular HTTP method.
*/ */
const requestApiCall = method => async params => { const requestApiCall = (method) => async (params) => {
const { url, cache = false } = params const { url, cache = false } = params
const fixedUrl = `/${url}`.replace("//", "/") const fixedUrl = `/${url}`.replace("//", "/")
const enrichedParams = { ...params, method, url: fixedUrl } const enrichedParams = { ...params, method, url: fixedUrl }

View File

@ -3,7 +3,7 @@ import API from "./api"
/** /**
* Fetches screen definition for an app. * Fetches screen definition for an app.
*/ */
export const fetchAppDefinition = async appId => { export const fetchAppDefinition = async (appId) => {
return await API.get({ return await API.get({
url: `/api/applications/${appId}/definition`, url: `/api/applications/${appId}/definition`,
}) })

View File

@ -3,7 +3,7 @@ import API from "./api"
/** /**
* Uploads an attachment to the server. * Uploads an attachment to the server.
*/ */
export const uploadAttachment = async data => { export const uploadAttachment = async (data) => {
return await API.post({ return await API.post({
url: "/api/attachments/upload", url: "/api/attachments/upload",
body: data, body: data,

View File

@ -7,7 +7,7 @@ import { executeQuery } from "./queries"
/** /**
* Fetches all rows for a particular Budibase data source. * Fetches all rows for a particular Budibase data source.
*/ */
export const fetchDatasource = async dataSource => { export const fetchDatasource = async (dataSource) => {
if (!dataSource || !dataSource.type) { if (!dataSource || !dataSource.type) {
return [] return []
} }

View File

@ -18,7 +18,7 @@ export const fetchRow = async ({ tableId, rowId }) => {
/** /**
* Creates a row in a table. * Creates a row in a table.
*/ */
export const saveRow = async row => { export const saveRow = async (row) => {
if (!row?.tableId) { if (!row?.tableId) {
return return
} }
@ -39,7 +39,7 @@ export const saveRow = async row => {
/** /**
* Updates a row in a table. * Updates a row in a table.
*/ */
export const updateRow = async row => { export const updateRow = async (row) => {
if (!row?.tableId || !row?._id) { if (!row?.tableId || !row?._id) {
return return
} }
@ -115,15 +115,15 @@ export const enrichRows = async (rows, tableId) => {
const schema = tableDefinition && tableDefinition.schema const schema = tableDefinition && tableDefinition.schema
if (schema) { if (schema) {
const keys = Object.keys(schema) const keys = Object.keys(schema)
rows.forEach(row => { rows.forEach((row) => {
for (let key of keys) { for (let key of keys) {
const type = schema[key].type const type = schema[key].type
if (type === "link") { if (type === "link") {
// Enrich row a string join of relationship fields // Enrich row a string join of relationship fields
row[`${key}_text`] = row[`${key}_text`] =
row[key] row[key]
?.map(option => option?.primaryDisplay) ?.map((option) => option?.primaryDisplay)
.filter(option => !!option) .filter((option) => !!option)
.join(", ") || "" .join(", ") || ""
} else if (type === "attachment") { } else if (type === "attachment") {
// Enrich row with the first image URL for any attachment fields // Enrich row with the first image URL for any attachment fields

View File

@ -5,14 +5,14 @@ import { enrichRows } from "./rows"
* Fetches a table definition. * Fetches a table definition.
* Since definitions cannot change at runtime, the result is cached. * Since definitions cannot change at runtime, the result is cached.
*/ */
export const fetchTableDefinition = async tableId => { export const fetchTableDefinition = async (tableId) => {
return await API.get({ url: `/api/tables/${tableId}`, cache: true }) return await API.get({ url: `/api/tables/${tableId}`, cache: true })
} }
/** /**
* Fetches all rows from a table. * Fetches all rows from a table.
*/ */
export const fetchTableData = async tableId => { export const fetchTableData = async (tableId) => {
const rows = await API.get({ url: `/api/${tableId}/rows` }) const rows = await API.get({ url: `/api/${tableId}/rows` })
return await enrichRows(rows, tableId) return await enrichRows(rows, tableId)
} }

View File

@ -12,7 +12,7 @@ const createBuilderStore = () => {
} }
const store = writable(initialState) const store = writable(initialState)
const actions = { const actions = {
selectComponent: id => { selectComponent: (id) => {
if (id) { if (id) {
window.dispatchEvent( window.dispatchEvent(
new CustomEvent("bb-select-component", { detail: id }) new CustomEvent("bb-select-component", { detail: id })

View File

@ -1,9 +1,9 @@
import { writable, derived } from "svelte/store" import { writable, derived } from "svelte/store"
export const createContextStore = oldContext => { export const createContextStore = (oldContext) => {
const newContext = writable({}) const newContext = writable({})
const contexts = oldContext ? [oldContext, newContext] : [newContext] const contexts = oldContext ? [oldContext, newContext] : [newContext]
const totalContext = derived(contexts, $contexts => { const totalContext = derived(contexts, ($contexts) => {
return $contexts.reduce((total, context) => ({ ...total, ...context }), {}) return $contexts.reduce((total, context) => ({ ...total, ...context }), {})
}) })
@ -12,7 +12,7 @@ export const createContextStore = oldContext => {
if (!providerId || data === undefined) { if (!providerId || data === undefined) {
return return
} }
newContext.update(state => { newContext.update((state) => {
state[providerId] = data state[providerId] = data
// Keep track of the closest component ID so we can later hydrate a "data" prop. // Keep track of the closest component ID so we can later hydrate a "data" prop.
@ -29,7 +29,7 @@ export const createContextStore = oldContext => {
if (!providerId || !actionType) { if (!providerId || !actionType) {
return return
} }
newContext.update(state => { newContext.update((state) => {
state[`${providerId}_${actionType}`] = callback state[`${providerId}_${actionType}`] = callback
return state return state
}) })

View File

@ -40,8 +40,8 @@ export const createDataSourceStore = () => {
// Store configs for each relevant dataSource ID // Store configs for each relevant dataSource ID
if (dataSourceIds.length) { if (dataSourceIds.length) {
store.update(state => { store.update((state) => {
dataSourceIds.forEach(id => { dataSourceIds.forEach((id) => {
state.push({ state.push({
dataSourceId: id, dataSourceId: id,
instanceId, instanceId,
@ -55,22 +55,22 @@ export const createDataSourceStore = () => {
// Removes all registered dataSource instances belonging to a particular // Removes all registered dataSource instances belonging to a particular
// instance ID // instance ID
const unregisterInstance = instanceId => { const unregisterInstance = (instanceId) => {
store.update(state => { store.update((state) => {
return state.filter(instance => instance.instanceId !== instanceId) return state.filter((instance) => instance.instanceId !== instanceId)
}) })
} }
// Invalidates a specific dataSource ID by refreshing all instances // Invalidates a specific dataSource ID by refreshing all instances
// which depend on data from that dataSource // which depend on data from that dataSource
const invalidateDataSource = dataSourceId => { const invalidateDataSource = (dataSourceId) => {
const relatedInstances = get(store).filter(instance => { const relatedInstances = get(store).filter((instance) => {
return instance.dataSourceId === dataSourceId return instance.dataSourceId === dataSourceId
}) })
if (relatedInstances?.length) { if (relatedInstances?.length) {
notificationStore.blockNotifications(1000) notificationStore.blockNotifications(1000)
} }
relatedInstances?.forEach(instance => { relatedInstances?.forEach((instance) => {
instance.refresh() instance.refresh()
}) })
} }

View File

@ -7,7 +7,7 @@ const createNotificationStore = () => {
const _notifications = writable([], () => { const _notifications = writable([], () => {
return () => { return () => {
// clear all the timers // clear all the timers
timeoutIds.forEach(timeoutId => { timeoutIds.forEach((timeoutId) => {
clearTimeout(timeoutId) clearTimeout(timeoutId)
}) })
_notifications.set([]) _notifications.set([])
@ -25,11 +25,11 @@ const createNotificationStore = () => {
return return
} }
let _id = id() let _id = id()
_notifications.update(state => { _notifications.update((state) => {
return [...state, { id: _id, type, message }] return [...state, { id: _id, type, message }]
}) })
const timeoutId = setTimeout(() => { const timeoutId = setTimeout(() => {
_notifications.update(state => { _notifications.update((state) => {
return state.filter(({ id }) => id !== _id) return state.filter(({ id }) => id !== _id)
}) })
}, NOTIFICATION_TIMEOUT) }, NOTIFICATION_TIMEOUT)
@ -41,21 +41,16 @@ const createNotificationStore = () => {
return { return {
subscribe, subscribe,
send, send,
danger: msg => send(msg, "danger"), danger: (msg) => send(msg, "danger"),
warning: msg => send(msg, "warning"), warning: (msg) => send(msg, "warning"),
info: msg => send(msg, "info"), info: (msg) => send(msg, "info"),
success: msg => send(msg, "success"), success: (msg) => send(msg, "success"),
blockNotifications, blockNotifications,
} }
} }
function id() { function id() {
return ( return "_" + Math.random().toString(36).substr(2, 9)
"_" +
Math.random()
.toString(36)
.substr(2, 9)
)
} }
export const notificationStore = createNotificationStore() export const notificationStore = createNotificationStore()

View File

@ -14,7 +14,7 @@ const createRouteStore = () => {
const fetchRoutes = async () => { const fetchRoutes = async () => {
const routeConfig = await API.fetchRoutes() const routeConfig = await API.fetchRoutes()
let routes = [] let routes = []
Object.values(routeConfig.routes).forEach(route => { Object.values(routeConfig.routes).forEach((route) => {
Object.entries(route.subpaths).forEach(([path, config]) => { Object.entries(route.subpaths).forEach(([path, config]) => {
routes.push({ routes.push({
path, path,
@ -28,21 +28,21 @@ const createRouteStore = () => {
return a.path > b.path ? -1 : 1 return a.path > b.path ? -1 : 1
}) })
store.update(state => { store.update((state) => {
state.routes = routes state.routes = routes
state.routeSessionId = Math.random() state.routeSessionId = Math.random()
return state return state
}) })
} }
const setRouteParams = routeParams => { const setRouteParams = (routeParams) => {
store.update(state => { store.update((state) => {
state.routeParams = routeParams state.routeParams = routeParams
return state return state
}) })
} }
const setActiveRoute = route => { const setActiveRoute = (route) => {
store.update(state => { store.update((state) => {
state.activeRoute = state.routes.find(x => x.path === route) state.activeRoute = state.routes.find((x) => x.path === route)
return state return state
}) })
} }

View File

@ -25,12 +25,12 @@ const createScreenStore = () => {
activeScreen = screens[0] activeScreen = screens[0]
} else if ($routeStore.activeRoute) { } else if ($routeStore.activeRoute) {
activeScreen = screens.find( activeScreen = screens.find(
screen => screen._id === $routeStore.activeRoute.screenId (screen) => screen._id === $routeStore.activeRoute.screenId
) )
} }
if (activeScreen) { if (activeScreen) {
activeLayout = layouts.find( activeLayout = layouts.find(
layout => layout._id === activeScreen.layoutId (layout) => layout._id === activeScreen.layoutId
) )
} }
} }

View File

@ -16,27 +16,27 @@ const saveRowHandler = async (action, context) => {
} }
} }
const deleteRowHandler = async action => { const deleteRowHandler = async (action) => {
const { tableId, revId, rowId } = action.parameters const { tableId, revId, rowId } = action.parameters
if (tableId && revId && rowId) { if (tableId && revId && rowId) {
await deleteRow({ tableId, rowId, revId }) await deleteRow({ tableId, rowId, revId })
} }
} }
const triggerAutomationHandler = async action => { const triggerAutomationHandler = async (action) => {
const { fields } = action.parameters const { fields } = action.parameters
if (fields) { if (fields) {
await triggerAutomation(action.parameters.automationId, fields) await triggerAutomation(action.parameters.automationId, fields)
} }
} }
const navigationHandler = action => { const navigationHandler = (action) => {
if (action.parameters.url) { if (action.parameters.url) {
routeStore.actions.navigate(action.parameters.url) routeStore.actions.navigate(action.parameters.url)
} }
} }
const queryExecutionHandler = async action => { const queryExecutionHandler = async (action) => {
const { datasourceId, queryId, queryParams } = action.parameters const { datasourceId, queryId, queryParams } = action.parameters
await executeQuery({ await executeQuery({
datasourceId, datasourceId,
@ -68,7 +68,7 @@ const refreshDatasourceHandler = async (action, context) => {
) )
} }
const loginHandler = async action => { const loginHandler = async (action) => {
const { email, password } = action.parameters const { email, password } = action.parameters
await authStore.actions.logIn({ email, password }) await authStore.actions.logIn({ email, password })
} }
@ -98,7 +98,7 @@ export const enrichButtonActions = (actions, context) => {
if (get(builderStore).inBuilder) { if (get(builderStore).inBuilder) {
return () => {} return () => {}
} }
const handlers = actions.map(def => handlerMap[def["##eventHandlerType"]]) const handlers = actions.map((def) => handlerMap[def["##eventHandlerType"]])
return async () => { return async () => {
for (let i = 0; i < handlers.length; i++) { for (let i = 0; i < handlers.length; i++) {
try { try {

View File

@ -1,4 +1,4 @@
export const hashString = str => { export const hashString = (str) => {
if (!str) { if (!str) {
return 0 return 0
} }

View File

@ -53,7 +53,7 @@ export const styleable = (node, styles = {}) => {
} }
// Applies a style string to a DOM node // Applies a style string to a DOM node
const applyStyles = styleString => { const applyStyles = (styleString) => {
node.style = addBuilderPreviewStyles(node, styleString, componentId) node.style = addBuilderPreviewStyles(node, styleString, componentId)
node.dataset.componentId = componentId node.dataset.componentId = componentId
} }
@ -70,7 +70,7 @@ export const styleable = (node, styles = {}) => {
// Handler to select a component in the builder when clicking it in the // Handler to select a component in the builder when clicking it in the
// builder preview // builder preview
selectComponent = event => { selectComponent = (event) => {
builderStore.actions.selectComponent(componentId) builderStore.actions.selectComponent(componentId)
event.preventDefault() event.preventDefault()
event.stopPropagation() event.stopPropagation()
@ -106,7 +106,7 @@ export const styleable = (node, styles = {}) => {
return { return {
// Clean up old listeners and apply new ones on update // Clean up old listeners and apply new ones on update
update: newStyles => { update: (newStyles) => {
removeListeners() removeListeners()
setupStyles(newStyles) setupStyles(newStyles)
}, },

View File

@ -1,6 +1,6 @@
const elastic = {} const elastic = {}
elastic.Client = function() { elastic.Client = function () {
this.index = jest.fn().mockResolvedValue({ body: [] }) this.index = jest.fn().mockResolvedValue({ body: [] })
this.search = jest.fn().mockResolvedValue({ this.search = jest.fn().mockResolvedValue({
body: { body: {

View File

@ -1,6 +1,6 @@
const arangodb = {} const arangodb = {}
arangodb.Database = function() { arangodb.Database = function () {
this.query = jest.fn(() => ({ this.query = jest.fn(() => ({
all: jest.fn(), all: jest.fn(),
})) }))

View File

@ -1,6 +1,6 @@
const aws = {} const aws = {}
const response = body => () => ({ promise: () => body }) const response = (body) => () => ({ promise: () => body })
function DocumentClient() { function DocumentClient() {
this.put = jest.fn(response({})) this.put = jest.fn(response({}))

View File

@ -1,6 +1,6 @@
const mongodb = {} const mongodb = {}
mongodb.MongoClient = function() { mongodb.MongoClient = function () {
this.connect = jest.fn() this.connect = jest.fn()
this.close = jest.fn() this.close = jest.fn()
this.insertOne = jest.fn() this.insertOne = jest.fn()

View File

@ -46,7 +46,7 @@ async function init() {
SELF_HOSTED: 1, SELF_HOSTED: 1,
} }
let envFile = "" let envFile = ""
Object.keys(envFileJson).forEach(key => { Object.keys(envFileJson).forEach((key) => {
envFile += `${key}=${envFileJson[key]}\n` envFile += `${key}=${envFileJson[key]}\n`
}) })
fs.writeFileSync(envFilePath, envFile) fs.writeFileSync(envFilePath, envFile)
@ -78,7 +78,7 @@ const managementCommand = process.argv.slice(2)[0]
if ( if (
!managementCommand || !managementCommand ||
!Object.values(Commands).some(command => managementCommand === command) !Object.values(Commands).some((command) => managementCommand === command)
) { ) {
throw new Error( throw new Error(
"You must supply either an 'up', 'down' or 'nuke' commmand to manage the budibase development environment." "You must supply either an 'up', 'down' or 'nuke' commmand to manage the budibase development environment."
@ -104,7 +104,7 @@ command()
.then(() => { .then(() => {
console.log("Done! 🎉") console.log("Done! 🎉")
}) })
.catch(err => { .catch((err) => {
console.error( console.error(
"Something went wrong while managing budibase dev environment:", "Something went wrong while managing budibase dev environment:",
err.message err.message

View File

@ -25,7 +25,7 @@ yargs
type: "string", type: "string",
}, },
}, },
async args => { async (args) => {
if (!env.isDev()) { if (!env.isDev()) {
throw "Only works in dev" throw "Only works in dev"
} }

View File

@ -14,7 +14,7 @@ console.log(`Replicating from ${appName} to ${remoteUrl}/${appName}`)
const run = async () => { const run = async () => {
const allDbs = await CouchDB.allDbs() const allDbs = await CouchDB.allDbs()
const appDbNames = allDbs.filter(dbName => dbName.startsWith("inst_app")) const appDbNames = allDbs.filter((dbName) => dbName.startsWith("inst_app"))
let apps = [] let apps = []
for (let dbName of appDbNames) { for (let dbName of appDbNames) {
const db = new CouchDB(dbName) const db = new CouchDB(dbName)
@ -22,12 +22,12 @@ const run = async () => {
} }
apps = await Promise.all(apps) apps = await Promise.all(apps)
const app = apps.find( const app = apps.find(
a => a.name === appName || a.name.toLowerCase() === appName (a) => a.name === appName || a.name.toLowerCase() === appName
) )
if (!app) { if (!app) {
console.log( console.log(
`Could not find app... apps: ${apps.map(app => app.name).join(", ")}` `Could not find app... apps: ${apps.map((app) => app.name).join(", ")}`
) )
return return
} }
@ -37,10 +37,10 @@ const run = async () => {
instanceDb.replicate instanceDb.replicate
.to(remoteDb) .to(remoteDb)
.on("complete", function() { .on("complete", function () {
console.log("SUCCESS!") console.log("SUCCESS!")
}) })
.on("error", function(err) { .on("error", function (err) {
console.log(`FAILED: ${err}`) console.log(`FAILED: ${err}`)
}) })
} }

View File

@ -1,6 +1,6 @@
const env = require("../../environment") const env = require("../../environment")
exports.isEnabled = async function(ctx) { exports.isEnabled = async function (ctx) {
ctx.body = { ctx.body = {
enabled: env.ENABLE_ANALYTICS === "true", enabled: env.ENABLE_ANALYTICS === "true",
} }

View File

@ -1,6 +1,6 @@
const builderDB = require("../../db/builder") const builderDB = require("../../db/builder")
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
try { try {
const mainDoc = await builderDB.getBuilderMainDoc() const mainDoc = await builderDB.getBuilderMainDoc()
ctx.body = mainDoc.apiKeys ? mainDoc.apiKeys : {} ctx.body = mainDoc.apiKeys ? mainDoc.apiKeys : {}
@ -10,7 +10,7 @@ exports.fetch = async function(ctx) {
} }
} }
exports.update = async function(ctx) { exports.update = async function (ctx) {
const key = ctx.params.key const key = ctx.params.key
const value = ctx.request.body.value const value = ctx.request.body.value

View File

@ -43,7 +43,7 @@ async function getLayouts(db) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(row => row.doc) ).rows.map((row) => row.doc)
} }
async function getScreens(db) { async function getScreens(db) {
@ -53,7 +53,7 @@ async function getScreens(db) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(row => row.doc) ).rows.map((row) => row.doc)
} }
function getUserRoleId(ctx) { function getUserRoleId(ctx) {
@ -113,11 +113,11 @@ async function createInstance(template) {
return { _id: appId } return { _id: appId }
} }
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
ctx.body = await getAllApps() ctx.body = await getAllApps()
} }
exports.fetchAppDefinition = async function(ctx) { exports.fetchAppDefinition = async function (ctx) {
const db = new CouchDB(ctx.params.appId) const db = new CouchDB(ctx.params.appId)
const layouts = await getLayouts(db) const layouts = await getLayouts(db)
const userRoleId = getUserRoleId(ctx) const userRoleId = getUserRoleId(ctx)
@ -133,7 +133,7 @@ exports.fetchAppDefinition = async function(ctx) {
} }
} }
exports.fetchAppPackage = async function(ctx) { exports.fetchAppPackage = async function (ctx) {
const db = new CouchDB(ctx.params.appId) const db = new CouchDB(ctx.params.appId)
const application = await db.get(ctx.params.appId) const application = await db.get(ctx.params.appId)
const [layouts, screens] = await Promise.all([getLayouts(db), getScreens(db)]) const [layouts, screens] = await Promise.all([getLayouts(db), getScreens(db)])
@ -146,7 +146,7 @@ exports.fetchAppPackage = async function(ctx) {
} }
} }
exports.create = async function(ctx) { exports.create = async function (ctx) {
const { useTemplate, templateKey } = ctx.request.body const { useTemplate, templateKey } = ctx.request.body
const instanceConfig = { const instanceConfig = {
useTemplate, useTemplate,
@ -186,7 +186,7 @@ exports.create = async function(ctx) {
ctx.message = `Application ${ctx.request.body.name} created successfully` ctx.message = `Application ${ctx.request.body.name} created successfully`
} }
exports.update = async function(ctx) { exports.update = async function (ctx) {
const url = await getAppUrlIfNotInUse(ctx) const url = await getAppUrlIfNotInUse(ctx)
const db = new CouchDB(ctx.params.appId) const db = new CouchDB(ctx.params.appId)
const application = await db.get(ctx.params.appId) const application = await db.get(ctx.params.appId)
@ -202,7 +202,7 @@ exports.update = async function(ctx) {
ctx.body = response ctx.body = response
} }
exports.delete = async function(ctx) { exports.delete = async function (ctx) {
const db = new CouchDB(ctx.params.appId) const db = new CouchDB(ctx.params.appId)
const app = await db.get(ctx.params.appId) const app = await db.get(ctx.params.appId)
const result = await db.destroy() const result = await db.destroy()

View File

@ -3,7 +3,7 @@ const { outputProcessing } = require("../../utilities/rowProcessor")
const { InternalTables } = require("../../db/utils") const { InternalTables } = require("../../db/utils")
const { getFullUser } = require("../../utilities/users") const { getFullUser } = require("../../utilities/users")
exports.fetchSelf = async ctx => { exports.fetchSelf = async (ctx) => {
if (!ctx.user) { if (!ctx.user) {
ctx.throw(403, "No user logged in") ctx.throw(403, "No user logged in")
} }

View File

@ -93,7 +93,7 @@ async function checkForWebhooks({ appId, oldAuto, newAuto }) {
return newAuto return newAuto
} }
exports.create = async function(ctx) { exports.create = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
let automation = ctx.request.body let automation = ctx.request.body
automation.appId = ctx.appId automation.appId = ctx.appId
@ -124,7 +124,7 @@ exports.create = async function(ctx) {
} }
} }
exports.update = async function(ctx) { exports.update = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
let automation = ctx.request.body let automation = ctx.request.body
automation.appId = ctx.appId automation.appId = ctx.appId
@ -149,22 +149,22 @@ exports.update = async function(ctx) {
} }
} }
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const response = await db.allDocs( const response = await db.allDocs(
getAutomationParams(null, { getAutomationParams(null, {
include_docs: true, include_docs: true,
}) })
) )
ctx.body = response.rows.map(row => row.doc) ctx.body = response.rows.map((row) => row.doc)
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
ctx.body = await db.get(ctx.params.id) ctx.body = await db.get(ctx.params.id)
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const oldAutomation = await db.get(ctx.params.id) const oldAutomation = await db.get(ctx.params.id)
await checkForWebhooks({ await checkForWebhooks({
@ -174,19 +174,19 @@ exports.destroy = async function(ctx) {
ctx.body = await db.remove(ctx.params.id, ctx.params.rev) ctx.body = await db.remove(ctx.params.id, ctx.params.rev)
} }
exports.getActionList = async function(ctx) { exports.getActionList = async function (ctx) {
ctx.body = actions.DEFINITIONS ctx.body = actions.DEFINITIONS
} }
exports.getTriggerList = async function(ctx) { exports.getTriggerList = async function (ctx) {
ctx.body = triggers.BUILTIN_DEFINITIONS ctx.body = triggers.BUILTIN_DEFINITIONS
} }
exports.getLogicList = async function(ctx) { exports.getLogicList = async function (ctx) {
ctx.body = logic.BUILTIN_DEFINITIONS ctx.body = logic.BUILTIN_DEFINITIONS
} }
module.exports.getDefinitionList = async function(ctx) { module.exports.getDefinitionList = async function (ctx) {
ctx.body = { ctx.body = {
logic: logic.BUILTIN_DEFINITIONS, logic: logic.BUILTIN_DEFINITIONS,
trigger: triggers.BUILTIN_DEFINITIONS, trigger: triggers.BUILTIN_DEFINITIONS,
@ -200,7 +200,7 @@ module.exports.getDefinitionList = async function(ctx) {
* * * *
*********************/ *********************/
exports.trigger = async function(ctx) { exports.trigger = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
let automation = await db.get(ctx.params.id) let automation = await db.get(ctx.params.id)
await triggers.externalTrigger(automation, { await triggers.externalTrigger(automation, {

View File

@ -1,6 +1,6 @@
const { performBackup } = require("../../utilities/fileSystem") const { performBackup } = require("../../utilities/fileSystem")
exports.exportAppDump = async function(ctx) { exports.exportAppDump = async function (ctx) {
const { appId } = ctx.query const { appId } = ctx.query
const appname = decodeURI(ctx.query.appname) const appname = decodeURI(ctx.query.appname)
const backupIdentifier = `${appname}Backup${new Date().getTime()}.txt` const backupIdentifier = `${appname}Backup${new Date().getTime()}.txt`

View File

@ -1,13 +1,13 @@
const CouchDB = require("../../db") const CouchDB = require("../../db")
const { getComponentLibraryManifest } = require("../../utilities/fileSystem") const { getComponentLibraryManifest } = require("../../utilities/fileSystem")
exports.fetchAppComponentDefinitions = async function(ctx) { exports.fetchAppComponentDefinitions = async function (ctx) {
const appId = ctx.params.appId || ctx.appId const appId = ctx.params.appId || ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const app = await db.get(appId) const app = await db.get(appId)
let componentManifests = await Promise.all( let componentManifests = await Promise.all(
app.componentLibraries.map(async library => { app.componentLibraries.map(async (library) => {
let manifest = await getComponentLibraryManifest(appId, library) let manifest = await getComponentLibraryManifest(appId, library)
return { return {

View File

@ -5,7 +5,7 @@ const {
getQueryParams, getQueryParams,
} = require("../../db/utils") } = require("../../db/utils")
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const database = new CouchDB(ctx.appId) const database = new CouchDB(ctx.appId)
ctx.body = ( ctx.body = (
await database.allDocs( await database.allDocs(
@ -13,10 +13,10 @@ exports.fetch = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(row => row.doc) ).rows.map((row) => row.doc)
} }
exports.save = async function(ctx) { exports.save = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const datasource = { const datasource = {
@ -33,12 +33,12 @@ exports.save = async function(ctx) {
ctx.body = datasource ctx.body = datasource
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
// Delete all queries for the datasource // Delete all queries for the datasource
const rows = await db.allDocs(getQueryParams(ctx.params.datasourceId, null)) const rows = await db.allDocs(getQueryParams(ctx.params.datasourceId, null))
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true }))) await db.bulkDocs(rows.rows.map((row) => ({ ...row.doc, _deleted: true })))
// delete the datasource // delete the datasource
await db.remove(ctx.params.datasourceId, ctx.params.revId) await db.remove(ctx.params.datasourceId, ctx.params.revId)
@ -47,7 +47,7 @@ exports.destroy = async function(ctx) {
ctx.status = 200 ctx.status = 200
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
const database = new CouchDB(ctx.appId) const database = new CouchDB(ctx.appId)
ctx.body = await database.get(ctx.params.datasourceId) ctx.body = await database.get(ctx.params.datasourceId)
} }

View File

@ -13,7 +13,7 @@ const {
* Links to the "check-api-key" lambda. * Links to the "check-api-key" lambda.
* @param {object} deployment - information about the active deployment, including the appId and quota. * @param {object} deployment - information about the active deployment, including the appId and quota.
*/ */
exports.preDeployment = async function(deployment) { exports.preDeployment = async function (deployment) {
const json = await fetchCredentials(env.DEPLOYMENT_CREDENTIALS_URL, { const json = await fetchCredentials(env.DEPLOYMENT_CREDENTIALS_URL, {
apiKey: env.BUDIBASE_API_KEY, apiKey: env.BUDIBASE_API_KEY,
appId: deployment.getAppId(), appId: deployment.getAppId(),
@ -39,7 +39,7 @@ exports.preDeployment = async function(deployment) {
* @param {object} deployment information about the active deployment, including the quota info. * @param {object} deployment information about the active deployment, including the quota info.
* @returns {Promise<object>} The usage has been updated against the user API key. * @returns {Promise<object>} The usage has been updated against the user API key.
*/ */
exports.postDeployment = async function(deployment) { exports.postDeployment = async function (deployment) {
const DEPLOYMENT_SUCCESS_URL = const DEPLOYMENT_SUCCESS_URL =
env.DEPLOYMENT_CREDENTIALS_URL + "deploy/success" env.DEPLOYMENT_CREDENTIALS_URL + "deploy/success"
@ -62,14 +62,14 @@ exports.postDeployment = async function(deployment) {
return await response.json() return await response.json()
} }
exports.deploy = async function(deployment) { exports.deploy = async function (deployment) {
const appId = deployment.getAppId() const appId = deployment.getAppId()
const { bucket, accountId } = deployment.getVerification() const { bucket, accountId } = deployment.getVerification()
const metadata = { accountId } const metadata = { accountId }
await deployToObjectStore(appId, bucket, metadata) await deployToObjectStore(appId, bucket, metadata)
} }
exports.replicateDb = async function(deployment) { exports.replicateDb = async function (deployment) {
const appId = deployment.getAppId() const appId = deployment.getAppId()
const verification = deployment.getVerification() const verification = deployment.getVerification()
return performReplication( return performReplication(

View File

@ -91,7 +91,7 @@ async function deployApp(deployment) {
} }
} }
exports.fetchDeployments = async function(ctx) { exports.fetchDeployments = async function (ctx) {
try { try {
const db = new PouchDB(ctx.appId) const db = new PouchDB(ctx.appId)
const deploymentDoc = await db.get("_local/deployments") const deploymentDoc = await db.get("_local/deployments")
@ -108,7 +108,7 @@ exports.fetchDeployments = async function(ctx) {
} }
} }
exports.deploymentProgress = async function(ctx) { exports.deploymentProgress = async function (ctx) {
try { try {
const db = new PouchDB(ctx.appId) const db = new PouchDB(ctx.appId)
const deploymentDoc = await db.get("_local/deployments") const deploymentDoc = await db.get("_local/deployments")
@ -121,7 +121,7 @@ exports.deploymentProgress = async function(ctx) {
} }
} }
exports.deployApp = async function(ctx) { exports.deployApp = async function (ctx) {
// start by checking whether to deploy local or to cloud // start by checking whether to deploy local or to cloud
const hostingInfo = await getHostingInfo() const hostingInfo = await getHostingInfo()
deploymentService = deploymentService =

View File

@ -6,7 +6,7 @@ const {
ViewNames, ViewNames,
} = require("../../../db/utils") } = require("../../../db/utils")
exports.getAppQuota = async function(appId) { exports.getAppQuota = async function (appId) {
const db = new PouchDB(appId) const db = new PouchDB(appId)
const rows = await db.allDocs({ const rows = await db.allDocs({

View File

@ -10,7 +10,7 @@ const {
getSelfHostKey, getSelfHostKey,
} = require("../../../utilities/builder/hosting") } = require("../../../utilities/builder/hosting")
exports.preDeployment = async function() { exports.preDeployment = async function () {
const url = `${await getWorkerUrl()}/api/deploy` const url = `${await getWorkerUrl()}/api/deploy`
try { try {
const json = await fetchCredentials(url, { const json = await fetchCredentials(url, {
@ -37,11 +37,11 @@ exports.preDeployment = async function() {
} }
} }
exports.postDeployment = async function() { exports.postDeployment = async function () {
// we don't actively need to do anything after deployment in self hosting // we don't actively need to do anything after deployment in self hosting
} }
exports.deploy = async function(deployment) { exports.deploy = async function (deployment) {
const appId = deployment.getAppId() const appId = deployment.getAppId()
const verification = deployment.getVerification() const verification = deployment.getVerification()
// no metadata, aws has account ID in metadata // no metadata, aws has account ID in metadata
@ -49,7 +49,7 @@ exports.deploy = async function(deployment) {
await deployToObjectStore(appId, verification.bucket, metadata) await deployToObjectStore(appId, verification.bucket, metadata)
} }
exports.replicateDb = async function(deployment) { exports.replicateDb = async function (deployment) {
const appId = deployment.getAppId() const appId = deployment.getAppId()
const verification = deployment.getVerification() const verification = deployment.getVerification()
return performReplication( return performReplication(

View File

@ -22,7 +22,7 @@ function walkDir(dirPath, callback) {
} }
} }
exports.fetchCredentials = async function(url, body) { exports.fetchCredentials = async function (url, body) {
const response = await fetch(url, { const response = await fetch(url, {
method: "POST", method: "POST",
body: JSON.stringify(body), body: JSON.stringify(body),
@ -43,7 +43,7 @@ exports.fetchCredentials = async function(url, body) {
return json return json
} }
exports.prepareUpload = async function({ s3Key, bucket, metadata, file }) { exports.prepareUpload = async function ({ s3Key, bucket, metadata, file }) {
const response = await upload({ const response = await upload({
bucket, bucket,
metadata, metadata,
@ -62,13 +62,13 @@ exports.prepareUpload = async function({ s3Key, bucket, metadata, file }) {
} }
} }
exports.deployToObjectStore = async function(appId, bucket, metadata) { exports.deployToObjectStore = async function (appId, bucket, metadata) {
const appAssetsPath = join(budibaseAppsDir(), appId, "public") const appAssetsPath = join(budibaseAppsDir(), appId, "public")
let uploads = [] let uploads = []
// Upload HTML, CSS and JS for each page of the web app // Upload HTML, CSS and JS for each page of the web app
walkDir(appAssetsPath, function(filePath) { walkDir(appAssetsPath, function (filePath) {
const filePathParts = filePath.split("/") const filePathParts = filePath.split("/")
const appAssetUpload = exports.prepareUpload({ const appAssetUpload = exports.prepareUpload({
bucket, bucket,
@ -122,7 +122,7 @@ exports.performReplication = (appId, session, dbUrl) => {
const local = new PouchDB(appId) const local = new PouchDB(appId)
const remote = new CouchDB(`${dbUrl}/${appId}`, { const remote = new CouchDB(`${dbUrl}/${appId}`, {
fetch: function(url, opts) { fetch: function (url, opts) {
opts.headers.set("Cookie", `${session};`) opts.headers.set("Cookie", `${session};`)
return CouchDB.fetch(url, opts) return CouchDB.fetch(url, opts)
}, },
@ -131,6 +131,6 @@ exports.performReplication = (appId, session, dbUrl) => {
const replication = local.sync(remote) const replication = local.sync(remote)
replication.on("complete", () => resolve()) replication.on("complete", () => resolve())
replication.on("error", err => reject(err)) replication.on("error", (err) => reject(err))
}) })
} }

View File

@ -21,14 +21,14 @@ async function redirect(ctx, method) {
ctx.cookies ctx.cookies
} }
exports.redirectGet = async ctx => { exports.redirectGet = async (ctx) => {
await redirect(ctx, "GET") await redirect(ctx, "GET")
} }
exports.redirectPost = async ctx => { exports.redirectPost = async (ctx) => {
await redirect(ctx, "POST") await redirect(ctx, "POST")
} }
exports.redirectDelete = async ctx => { exports.redirectDelete = async (ctx) => {
await redirect(ctx, "DELETE") await redirect(ctx, "DELETE")
} }

View File

@ -7,13 +7,13 @@ const {
} = require("../../utilities/builder/hosting") } = require("../../utilities/builder/hosting")
const { StaticDatabases } = require("../../db/utils") const { StaticDatabases } = require("../../db/utils")
exports.fetchInfo = async ctx => { exports.fetchInfo = async (ctx) => {
ctx.body = { ctx.body = {
types: Object.values(HostingTypes), types: Object.values(HostingTypes),
} }
} }
exports.save = async ctx => { exports.save = async (ctx) => {
const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name) const db = new CouchDB(StaticDatabases.BUILDER_HOSTING.name)
const { type } = ctx.request.body const { type } = ctx.request.body
if (type === HostingTypes.CLOUD && ctx.request.body._rev) { if (type === HostingTypes.CLOUD && ctx.request.body._rev) {
@ -29,16 +29,16 @@ exports.save = async ctx => {
} }
} }
exports.fetch = async ctx => { exports.fetch = async (ctx) => {
ctx.body = await getHostingInfo() ctx.body = await getHostingInfo()
} }
exports.fetchUrls = async ctx => { exports.fetchUrls = async (ctx) => {
ctx.body = { ctx.body = {
app: await getAppUrl(ctx.appId), app: await getAppUrl(ctx.appId),
} }
} }
exports.getDeployedApps = async ctx => { exports.getDeployedApps = async (ctx) => {
ctx.body = await getDeployedApps(ctx) ctx.body = await getDeployedApps(ctx)
} }

View File

@ -1,12 +1,12 @@
const { definitions } = require("../../integrations") const { definitions } = require("../../integrations")
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
// TODO: fetch these from a github repo etc // TODO: fetch these from a github repo etc
ctx.status = 200 ctx.status = 200
ctx.body = definitions ctx.body = definitions
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
ctx.status = 200 ctx.status = 200
ctx.body = definitions[ctx.params.type] ctx.body = definitions[ctx.params.type]
} }

View File

@ -2,7 +2,7 @@ const { EMPTY_LAYOUT } = require("../../constants/layouts")
const CouchDB = require("../../db") const CouchDB = require("../../db")
const { generateLayoutID, getScreenParams } = require("../../db/utils") const { generateLayoutID, getScreenParams } = require("../../db/utils")
exports.save = async function(ctx) { exports.save = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
let layout = ctx.request.body let layout = ctx.request.body
@ -21,7 +21,7 @@ exports.save = async function(ctx) {
ctx.status = 200 ctx.status = 200
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const layoutId = ctx.params.layoutId, const layoutId = ctx.params.layoutId,
layoutRev = ctx.params.layoutRev layoutRev = ctx.params.layoutRev
@ -32,7 +32,7 @@ exports.destroy = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(element => element.doc.layoutId) ).rows.map((element) => element.doc.layoutId)
if (layoutsUsedByScreens.includes(layoutId)) { if (layoutsUsedByScreens.includes(layoutId)) {
ctx.throw(400, "Cannot delete a layout that's being used by a screen") ctx.throw(400, "Cannot delete a layout that's being used by a screen")
} }

View File

@ -47,7 +47,7 @@ async function getAllDBRoles(db) {
include_docs: true, include_docs: true,
}) })
) )
return body.rows.map(row => row.doc) return body.rows.map((row) => row.doc)
} }
async function updatePermissionOnRole( async function updatePermissionOnRole(
@ -63,7 +63,7 @@ async function updatePermissionOnRole(
const docUpdates = [] const docUpdates = []
// the permission is for a built in, make sure it exists // the permission is for a built in, make sure it exists
if (isABuiltin && !dbRoles.some(role => role._id === dbRoleId)) { if (isABuiltin && !dbRoles.some((role) => role._id === dbRoleId)) {
const builtin = getBuiltinRoles()[roleId] const builtin = getBuiltinRoles()[roleId]
builtin._id = getDBRoleID(builtin._id) builtin._id = getDBRoleID(builtin._id)
dbRoles.push(builtin) dbRoles.push(builtin)
@ -101,23 +101,23 @@ async function updatePermissionOnRole(
} }
const response = await db.bulkDocs(docUpdates) const response = await db.bulkDocs(docUpdates)
return response.map(resp => { return response.map((resp) => {
resp._id = getExternalRoleID(resp.id) resp._id = getExternalRoleID(resp.id)
delete resp.id delete resp.id
return resp return resp
}) })
} }
exports.fetchBuiltin = function(ctx) { exports.fetchBuiltin = function (ctx) {
ctx.body = Object.values(getBuiltinPermissions()) ctx.body = Object.values(getBuiltinPermissions())
} }
exports.fetchLevels = function(ctx) { exports.fetchLevels = function (ctx) {
// for now only provide the read/write perms externally // for now only provide the read/write perms externally
ctx.body = SUPPORTED_LEVELS ctx.body = SUPPORTED_LEVELS
} }
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const roles = await getAllDBRoles(db) const roles = await getAllDBRoles(db)
let permissions = {} let permissions = {}
@ -144,7 +144,7 @@ exports.fetch = async function(ctx) {
ctx.body = finalPermissions ctx.body = finalPermissions
} }
exports.getResourcePerms = async function(ctx) { exports.getResourcePerms = async function (ctx) {
const resourceId = ctx.params.resourceId const resourceId = ctx.params.resourceId
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const body = await db.allDocs( const body = await db.allDocs(
@ -152,7 +152,7 @@ exports.getResourcePerms = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
const roles = body.rows.map(row => row.doc) const roles = body.rows.map((row) => row.doc)
let permissions = {} let permissions = {}
for (let level of SUPPORTED_LEVELS) { for (let level of SUPPORTED_LEVELS) {
// update the various roleIds in the resource permissions // update the various roleIds in the resource permissions
@ -169,7 +169,7 @@ exports.getResourcePerms = async function(ctx) {
ctx.body = Object.assign(getBasePermissions(resourceId), permissions) ctx.body = Object.assign(getBasePermissions(resourceId), permissions)
} }
exports.addPermission = async function(ctx) { exports.addPermission = async function (ctx) {
ctx.body = await updatePermissionOnRole( ctx.body = await updatePermissionOnRole(
ctx.appId, ctx.appId,
ctx.params, ctx.params,
@ -177,7 +177,7 @@ exports.addPermission = async function(ctx) {
) )
} }
exports.removePermission = async function(ctx) { exports.removePermission = async function (ctx) {
ctx.body = await updatePermissionOnRole( ctx.body = await updatePermissionOnRole(
ctx.appId, ctx.appId,
ctx.params, ctx.params,

View File

@ -27,7 +27,7 @@ function formatResponse(resp) {
return resp return resp
} }
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const body = await db.allDocs( const body = await db.allDocs(
@ -35,10 +35,10 @@ exports.fetch = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
ctx.body = enrichQueries(body.rows.map(row => row.doc)) ctx.body = enrichQueries(body.rows.map((row) => row.doc))
} }
exports.save = async function(ctx) { exports.save = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const query = ctx.request.body const query = ctx.request.body
@ -89,7 +89,7 @@ async function enrichQueryFields(fields, parameters) {
return enrichedQuery return enrichedQuery
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const query = enrichQueries(await db.get(ctx.params.queryId)) const query = enrichQueries(await db.get(ctx.params.queryId))
// remove properties that could be dangerous in real app // remove properties that could be dangerous in real app
@ -101,7 +101,7 @@ exports.find = async function(ctx) {
ctx.body = query ctx.body = query
} }
exports.preview = async function(ctx) { exports.preview = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const datasource = await db.get(ctx.request.body.datasourceId) const datasource = await db.get(ctx.request.body.datasourceId)
@ -129,7 +129,7 @@ exports.preview = async function(ctx) {
} }
} }
exports.execute = async function(ctx) { exports.execute = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const query = await db.get(ctx.params.queryId) const query = await db.get(ctx.params.queryId)
@ -152,7 +152,7 @@ exports.execute = async function(ctx) {
) )
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
await db.remove(ctx.params.queryId, ctx.params.revId) await db.remove(ctx.params.queryId, ctx.params.revId)
ctx.message = `Query deleted.` ctx.message = `Query deleted.`

View File

@ -50,27 +50,27 @@ async function updateRolesOnUserTable(db, roleId, updateOption) {
} }
} }
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const body = await db.allDocs( const body = await db.allDocs(
getRoleParams(null, { getRoleParams(null, {
include_docs: true, include_docs: true,
}) })
) )
let roles = body.rows.map(row => row.doc) let roles = body.rows.map((row) => row.doc)
const builtinRoles = getBuiltinRoles() const builtinRoles = getBuiltinRoles()
// need to combine builtin with any DB record of them (for sake of permissions) // need to combine builtin with any DB record of them (for sake of permissions)
for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) { for (let builtinRoleId of EXTERNAL_BUILTIN_ROLE_IDS) {
const builtinRole = builtinRoles[builtinRoleId] const builtinRole = builtinRoles[builtinRoleId]
const dbBuiltin = roles.filter( const dbBuiltin = roles.filter(
dbRole => getExternalRoleID(dbRole._id) === builtinRoleId (dbRole) => getExternalRoleID(dbRole._id) === builtinRoleId
)[0] )[0]
if (dbBuiltin == null) { if (dbBuiltin == null) {
roles.push(builtinRole) roles.push(builtinRole)
} else { } else {
// remove role and all back after combining with the builtin // remove role and all back after combining with the builtin
roles = roles.filter(role => role._id !== dbBuiltin._id) roles = roles.filter((role) => role._id !== dbBuiltin._id)
dbBuiltin._id = getExternalRoleID(dbBuiltin._id) dbBuiltin._id = getExternalRoleID(dbBuiltin._id)
roles.push(Object.assign(builtinRole, dbBuiltin)) roles.push(Object.assign(builtinRole, dbBuiltin))
} }
@ -78,11 +78,11 @@ exports.fetch = async function(ctx) {
ctx.body = roles ctx.body = roles
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
ctx.body = await getRole(ctx.appId, ctx.params.roleId) ctx.body = await getRole(ctx.appId, ctx.params.roleId)
} }
exports.save = async function(ctx) { exports.save = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
let { _id, name, inherits, permissionId } = ctx.request.body let { _id, name, inherits, permissionId } = ctx.request.body
if (!_id) { if (!_id) {
@ -103,7 +103,7 @@ exports.save = async function(ctx) {
ctx.message = `Role '${role.name}' created successfully.` ctx.message = `Role '${role.name}' created successfully.`
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const roleId = ctx.params.roleId const roleId = ctx.params.roleId
if (isBuiltin(roleId)) { if (isBuiltin(roleId)) {
@ -116,8 +116,8 @@ exports.destroy = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(row => row.doc) ).rows.map((row) => row.doc)
const usersWithRole = users.filter(user => user.roleId === roleId) const usersWithRole = users.filter((user) => user.roleId === roleId)
if (usersWithRole.length !== 0) { if (usersWithRole.length !== 0) {
ctx.throw(400, "Cannot delete role when it is in use.") ctx.throw(400, "Cannot delete role when it is in use.")
} }

View File

@ -10,7 +10,7 @@ function Routing() {
this.json = {} this.json = {}
} }
Routing.prototype.getTopLevel = function(fullpath) { Routing.prototype.getTopLevel = function (fullpath) {
if (fullpath.charAt(0) !== URL_SEPARATOR) { if (fullpath.charAt(0) !== URL_SEPARATOR) {
fullpath = URL_SEPARATOR + fullpath fullpath = URL_SEPARATOR + fullpath
} }
@ -18,7 +18,7 @@ Routing.prototype.getTopLevel = function(fullpath) {
return URL_SEPARATOR + fullpath.split(URL_SEPARATOR)[1] return URL_SEPARATOR + fullpath.split(URL_SEPARATOR)[1]
} }
Routing.prototype.getScreensProp = function(fullpath) { Routing.prototype.getScreensProp = function (fullpath) {
const topLevel = this.getTopLevel(fullpath) const topLevel = this.getTopLevel(fullpath)
if (!this.json[topLevel]) { if (!this.json[topLevel]) {
this.json[topLevel] = { this.json[topLevel] = {
@ -33,7 +33,7 @@ Routing.prototype.getScreensProp = function(fullpath) {
return this.json[topLevel].subpaths[fullpath].screens return this.json[topLevel].subpaths[fullpath].screens
} }
Routing.prototype.addScreenId = function(fullpath, roleId, screenId) { Routing.prototype.addScreenId = function (fullpath, roleId, screenId) {
this.getScreensProp(fullpath)[roleId] = screenId this.getScreensProp(fullpath)[roleId] = screenId
} }
@ -56,11 +56,11 @@ async function getRoutingStructure(appId) {
return { routes: routing.json } return { routes: routing.json }
} }
exports.fetch = async ctx => { exports.fetch = async (ctx) => {
ctx.body = await getRoutingStructure(ctx.appId) ctx.body = await getRoutingStructure(ctx.appId)
} }
exports.clientFetch = async ctx => { exports.clientFetch = async (ctx) => {
const routing = await getRoutingStructure(ctx.appId) const routing = await getRoutingStructure(ctx.appId)
let roleId = ctx.user.role._id let roleId = ctx.user.role._id
// builder is a special case, always return the full routing structure // builder is a special case, always return the full routing structure

View File

@ -27,11 +27,11 @@ const CALCULATION_TYPES = {
} }
validateJs.extend(validateJs.validators.datetime, { validateJs.extend(validateJs.validators.datetime, {
parse: function(value) { parse: function (value) {
return new Date(value).getTime() return new Date(value).getTime()
}, },
// Input is a unix timestamp // Input is a unix timestamp
format: function(value) { format: function (value) {
return new Date(value).toISOString() return new Date(value).toISOString()
}, },
}) })
@ -54,7 +54,7 @@ async function findRow(ctx, db, tableId, rowId) {
return row return row
} }
exports.patch = async function(ctx) { exports.patch = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
let dbRow = await db.get(ctx.params.rowId) let dbRow = await db.get(ctx.params.rowId)
@ -115,7 +115,7 @@ exports.patch = async function(ctx) {
ctx.message = `${table.name} updated successfully.` ctx.message = `${table.name} updated successfully.`
} }
exports.save = async function(ctx) { exports.save = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
let inputs = ctx.request.body let inputs = ctx.request.body
@ -189,7 +189,7 @@ exports.save = async function(ctx) {
ctx.message = `${table.name} saved successfully` ctx.message = `${table.name} saved successfully`
} }
exports.fetchView = async function(ctx) { exports.fetchView = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const viewName = ctx.params.viewName const viewName = ctx.params.viewName
@ -213,7 +213,7 @@ exports.fetchView = async function(ctx) {
}) })
if (!calculation) { if (!calculation) {
response.rows = response.rows.map(row => row.doc) response.rows = response.rows.map((row) => row.doc)
let table let table
try { try {
table = await db.get(viewInfo.meta.tableId) table = await db.get(viewInfo.meta.tableId)
@ -227,7 +227,7 @@ exports.fetchView = async function(ctx) {
} }
if (calculation === CALCULATION_TYPES.STATS) { if (calculation === CALCULATION_TYPES.STATS) {
response.rows = response.rows.map(row => ({ response.rows = response.rows.map((row) => ({
group: row.key, group: row.key,
field, field,
...row.value, ...row.value,
@ -240,7 +240,7 @@ exports.fetchView = async function(ctx) {
calculation === CALCULATION_TYPES.COUNT || calculation === CALCULATION_TYPES.COUNT ||
calculation === CALCULATION_TYPES.SUM calculation === CALCULATION_TYPES.SUM
) { ) {
ctx.body = response.rows.map(row => ({ ctx.body = response.rows.map((row) => ({
group: row.key, group: row.key,
field, field,
value: row.value, value: row.value,
@ -248,7 +248,7 @@ exports.fetchView = async function(ctx) {
} }
} }
exports.search = async function(ctx) { exports.search = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const { const {
@ -287,7 +287,7 @@ exports.search = async function(ctx) {
} }
} }
exports.fetchTableRows = async function(ctx) { exports.fetchTableRows = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
@ -303,12 +303,12 @@ exports.fetchTableRows = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
rows = response.rows.map(row => row.doc) rows = response.rows.map((row) => row.doc)
} }
ctx.body = await outputProcessing(appId, table, rows) ctx.body = await outputProcessing(appId, table, rows)
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
try { try {
@ -320,7 +320,7 @@ exports.find = async function(ctx) {
} }
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const row = await db.get(ctx.params.rowId) const row = await db.get(ctx.params.rowId)
@ -349,7 +349,7 @@ exports.destroy = async function(ctx) {
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row) ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
} }
exports.validate = async function(ctx) { exports.validate = async function (ctx) {
const errors = await validate({ const errors = await validate({
appId: ctx.appId, appId: ctx.appId,
tableId: ctx.params.tableId, tableId: ctx.params.tableId,
@ -380,7 +380,7 @@ async function validate({ appId, tableId, row, table }) {
return { valid: Object.keys(errors).length === 0, errors } return { valid: Object.keys(errors).length === 0, errors }
} }
exports.fetchEnrichedRow = async function(ctx) { exports.fetchEnrichedRow = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const tableId = ctx.params.tableId const tableId = ctx.params.tableId
@ -399,13 +399,13 @@ exports.fetchEnrichedRow = async function(ctx) {
// look up the actual rows based on the ids // look up the actual rows based on the ids
const response = await db.allDocs({ const response = await db.allDocs({
include_docs: true, include_docs: true,
keys: linkVals.map(linkVal => linkVal.id), keys: linkVals.map((linkVal) => linkVal.id),
}) })
// need to include the IDs in these rows for any links they may have // need to include the IDs in these rows for any links they may have
let linkedRows = await outputProcessing( let linkedRows = await outputProcessing(
appId, appId,
table, table,
response.rows.map(row => row.doc) response.rows.map((row) => row.doc)
) )
// insert the link rows in the correct place throughout the main row // insert the link rows in the correct place throughout the main row
for (let fieldName of Object.keys(table.schema)) { for (let fieldName of Object.keys(table.schema)) {
@ -413,8 +413,8 @@ exports.fetchEnrichedRow = async function(ctx) {
if (field.type === FieldTypes.LINK) { if (field.type === FieldTypes.LINK) {
// find the links that pertain to this field, get their indexes // find the links that pertain to this field, get their indexes
const linkIndexes = linkVals const linkIndexes = linkVals
.filter(link => link.fieldName === fieldName) .filter((link) => link.fieldName === fieldName)
.map(link => linkVals.indexOf(link)) .map((link) => linkVals.indexOf(link))
// find the rows that the links state are linked to this field // find the rows that the links state are linked to this field
row[fieldName] = linkedRows.filter((linkRow, index) => row[fieldName] = linkedRows.filter((linkRow, index) =>
linkIndexes.includes(index) linkIndexes.includes(index)
@ -430,7 +430,7 @@ async function bulkDelete(ctx) {
const { rows } = ctx.request.body const { rows } = ctx.request.body
const db = new CouchDB(appId) const db = new CouchDB(appId)
let updates = rows.map(row => let updates = rows.map((row) =>
linkRows.updateLinks({ linkRows.updateLinks({
appId, appId,
eventType: linkRows.EventType.ROW_DELETE, eventType: linkRows.EventType.ROW_DELETE,
@ -441,7 +441,7 @@ async function bulkDelete(ctx) {
// TODO remove special user case in future // TODO remove special user case in future
if (ctx.params.tableId === InternalTables.USER_METADATA) { if (ctx.params.tableId === InternalTables.USER_METADATA) {
updates = updates.concat( updates = updates.concat(
rows.map(row => { rows.map((row) => {
ctx.params = { ctx.params = {
id: row._id, id: row._id,
} }
@ -449,11 +449,11 @@ async function bulkDelete(ctx) {
}) })
) )
} else { } else {
await db.bulkDocs(rows.map(row => ({ ...row, _deleted: true }))) await db.bulkDocs(rows.map((row) => ({ ...row, _deleted: true })))
} }
await Promise.all(updates) await Promise.all(updates)
rows.forEach(row => { rows.forEach((row) => {
ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row) ctx.eventEmitter && ctx.eventEmitter.emitRow(`row:delete`, appId, row)
}) })
} }

View File

@ -2,7 +2,7 @@ const CouchDB = require("../../db")
const { getScreenParams, generateScreenID } = require("../../db/utils") const { getScreenParams, generateScreenID } = require("../../db/utils")
const { AccessController } = require("../../utilities/security/roles") const { AccessController } = require("../../utilities/security/roles")
exports.fetch = async ctx => { exports.fetch = async (ctx) => {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
@ -12,7 +12,7 @@ exports.fetch = async ctx => {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(element => element.doc) ).rows.map((element) => element.doc)
ctx.body = await new AccessController(appId).checkScreensAccess( ctx.body = await new AccessController(appId).checkScreensAccess(
screens, screens,
@ -20,7 +20,7 @@ exports.fetch = async ctx => {
) )
} }
exports.save = async ctx => { exports.save = async (ctx) => {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
let screen = ctx.request.body let screen = ctx.request.body
@ -38,7 +38,7 @@ exports.save = async ctx => {
} }
} }
exports.destroy = async ctx => { exports.destroy = async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
await db.remove(ctx.params.screenId, ctx.params.screenRev) await db.remove(ctx.params.screenId, ctx.params.screenRev)
ctx.body = { ctx.body = {

View File

@ -1,6 +1,6 @@
const { QueryBuilder, buildSearchUrl, search } = require("./utils") const { QueryBuilder, buildSearchUrl, search } = require("./utils")
exports.rowSearch = async ctx => { exports.rowSearch = async (ctx) => {
const appId = ctx.appId const appId = ctx.appId
const { tableId } = ctx.params const { tableId } = ctx.params
const { bookmark, query, raw } = ctx.request.body const { bookmark, query, raw } = ctx.request.body

View File

@ -116,7 +116,7 @@ class QueryBuilder {
} }
} }
exports.search = async query => { exports.search = async (query) => {
const response = await fetch(query, { const response = await fetch(query, {
method: "GET", method: "GET",
}) })
@ -125,7 +125,7 @@ exports.search = async query => {
rows: [], rows: [],
} }
if (json.rows != null && json.rows.length > 0) { if (json.rows != null && json.rows.length > 0) {
output.rows = json.rows.map(row => row.doc) output.rows = json.rows.map((row) => row.doc)
} }
if (json.bookmark) { if (json.bookmark) {
output.bookmark = json.bookmark output.bookmark = json.bookmark

View File

@ -15,7 +15,7 @@ const {
TOP_LEVEL_PATH, TOP_LEVEL_PATH,
} = require("../../../utilities/fileSystem") } = require("../../../utilities/fileSystem")
const env = require("../../../environment") const env = require("../../../environment")
const fileProcessor = require("../../../utilities/fileSystem/processor") // const fileProcessor = require("../../../utilities/fileSystem/processor")
const { objectStoreUrl, clientLibraryPath } = require("../../../utilities") const { objectStoreUrl, clientLibraryPath } = require("../../../utilities")
async function checkForSelfHostedURL(ctx) { async function checkForSelfHostedURL(ctx) {
@ -32,18 +32,18 @@ async function checkForSelfHostedURL(ctx) {
// this was the version before we started versioning the component library // this was the version before we started versioning the component library
const COMP_LIB_BASE_APP_VERSION = "0.2.5" const COMP_LIB_BASE_APP_VERSION = "0.2.5"
exports.serveBuilder = async function(ctx) { exports.serveBuilder = async function (ctx) {
let builderPath = resolve(TOP_LEVEL_PATH, "builder") let builderPath = resolve(TOP_LEVEL_PATH, "builder")
await send(ctx, ctx.file, { root: builderPath }) await send(ctx, ctx.file, { root: builderPath })
} }
exports.uploadFile = async function(ctx) { exports.uploadFile = async function (ctx) {
let files = let files =
ctx.request.files.file.length > 1 ctx.request.files.file.length > 1
? Array.from(ctx.request.files.file) ? Array.from(ctx.request.files.file)
: [ctx.request.files.file] : [ctx.request.files.file]
const uploads = files.map(async file => { const uploads = files.map(async (file) => {
const fileExtension = [...file.name.split(".")].pop() const fileExtension = [...file.name.split(".")].pop()
// filenames converted to UUIDs so they are unique // filenames converted to UUIDs so they are unique
const processedFileName = `${uuid.v4()}.${fileExtension}` const processedFileName = `${uuid.v4()}.${fileExtension}`
@ -65,7 +65,7 @@ exports.uploadFile = async function(ctx) {
ctx.body = await Promise.all(uploads) ctx.body = await Promise.all(uploads)
} }
exports.serveApp = async function(ctx) { exports.serveApp = async function (ctx) {
let appId = ctx.params.appId let appId = ctx.params.appId
if (env.SELF_HOSTED) { if (env.SELF_HOSTED) {
appId = await checkForSelfHostedURL(ctx) appId = await checkForSelfHostedURL(ctx)
@ -90,13 +90,13 @@ exports.serveApp = async function(ctx) {
}) })
} }
exports.serveClientLibrary = async function(ctx) { exports.serveClientLibrary = async function (ctx) {
return send(ctx, "budibase-client.js", { return send(ctx, "budibase-client.js", {
root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"), root: join(NODE_MODULES_PATH, "@budibase", "client", "dist"),
}) })
} }
exports.serveComponentLibrary = async function(ctx) { exports.serveComponentLibrary = async function (ctx) {
const appId = ctx.query.appId || ctx.appId const appId = ctx.query.appId || ctx.appId
if (env.isDev() || env.isTest()) { if (env.isDev() || env.isTest()) {

View File

@ -9,22 +9,22 @@ const {
const { FieldTypes } = require("../../../constants") const { FieldTypes } = require("../../../constants")
const { TableSaveFunctions } = require("./utils") const { TableSaveFunctions } = require("./utils")
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const body = await db.allDocs( const body = await db.allDocs(
getTableParams(null, { getTableParams(null, {
include_docs: true, include_docs: true,
}) })
) )
ctx.body = body.rows.map(row => row.doc) ctx.body = body.rows.map((row) => row.doc)
} }
exports.find = async function(ctx) { exports.find = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
ctx.body = await db.get(ctx.params.id) ctx.body = await db.get(ctx.params.id)
} }
exports.save = async function(ctx) { exports.save = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const { dataImport, ...rest } = ctx.request.body const { dataImport, ...rest } = ctx.request.body
@ -126,7 +126,7 @@ exports.save = async function(ctx) {
ctx.body = tableToSave ctx.body = tableToSave
} }
exports.destroy = async function(ctx) { exports.destroy = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const tableToDelete = await db.get(ctx.params.tableId) const tableToDelete = await db.get(ctx.params.tableId)
@ -137,7 +137,7 @@ exports.destroy = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
await db.bulkDocs(rows.rows.map(row => ({ ...row.doc, _deleted: true }))) await db.bulkDocs(rows.rows.map((row) => ({ ...row.doc, _deleted: true })))
// update linked rows // update linked rows
await linkRows.updateLinks({ await linkRows.updateLinks({
@ -152,7 +152,7 @@ exports.destroy = async function(ctx) {
// remove table search index // remove table search index
const currentIndexes = await db.getIndexes() const currentIndexes = await db.getIndexes()
const existingIndex = currentIndexes.indexes.find( const existingIndex = currentIndexes.indexes.find(
existing => existing.name === `search:${ctx.params.tableId}` (existing) => existing.name === `search:${ctx.params.tableId}`
) )
if (existingIndex) { if (existingIndex) {
await db.deleteIndex(existingIndex) await db.deleteIndex(existingIndex)
@ -164,7 +164,7 @@ exports.destroy = async function(ctx) {
ctx.body = { message: `Table ${ctx.params.tableId} deleted.` } ctx.body = { message: `Table ${ctx.params.tableId} deleted.` }
} }
exports.validateCSVSchema = async function(ctx) { exports.validateCSVSchema = async function (ctx) {
const { csvString, schema = {} } = ctx.request.body const { csvString, schema = {} } = ctx.request.body
const result = await csvParser.parse(csvString, schema) const result = await csvParser.parse(csvString, schema)
ctx.body = { schema: result } ctx.body = { schema: result }

View File

@ -16,7 +16,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
let deletedColumns = [] let deletedColumns = []
if (oldTable && oldTable.schema && updatedTable.schema) { if (oldTable && oldTable.schema && updatedTable.schema) {
deletedColumns = Object.keys(oldTable.schema).filter( deletedColumns = Object.keys(oldTable.schema).filter(
colName => updatedTable.schema[colName] == null (colName) => updatedTable.schema[colName] == null
) )
} }
// check for renaming of columns or deleted columns // check for renaming of columns or deleted columns
@ -31,7 +31,7 @@ exports.checkForColumnUpdates = async (db, oldTable, updatedTable) => {
doc[rename.updated] = doc[rename.old] doc[rename.updated] = doc[rename.old]
delete doc[rename.old] delete doc[rename.old]
} else if (deletedColumns.length !== 0) { } else if (deletedColumns.length !== 0) {
deletedColumns.forEach(colName => delete doc[colName]) deletedColumns.forEach((colName) => delete doc[colName])
} }
return doc return doc
}) })
@ -102,12 +102,12 @@ exports.handleSearchIndexes = async (appId, table) => {
const indexName = `search:${table._id}` const indexName = `search:${table._id}`
const existingIndex = currentIndexes.indexes.find( const existingIndex = currentIndexes.indexes.find(
existing => existing.name === indexName (existing) => existing.name === indexName
) )
if (existingIndex) { if (existingIndex) {
const currentFields = existingIndex.def.fields.map( const currentFields = existingIndex.def.fields.map(
field => Object.keys(field)[0] (field) => Object.keys(field)[0]
) )
// if index fields have changed, delete the original index // if index fields have changed, delete the original index
@ -138,7 +138,7 @@ exports.handleSearchIndexes = async (appId, table) => {
return table return table
} }
exports.checkStaticTables = table => { exports.checkStaticTables = (table) => {
// check user schema has all required elements // check user schema has all required elements
if (table._id === InternalTables.USER_METADATA) { if (table._id === InternalTables.USER_METADATA) {
for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) { for (let [key, schema] of Object.entries(USERS_TABLE_SCHEMA.schema)) {

View File

@ -5,7 +5,7 @@ const { downloadTemplate } = require("../../utilities/fileSystem")
const DEFAULT_TEMPLATES_BUCKET = const DEFAULT_TEMPLATES_BUCKET =
"prod-budi-templates.s3-eu-west-1.amazonaws.com" "prod-budi-templates.s3-eu-west-1.amazonaws.com"
exports.fetch = async function(ctx) { exports.fetch = async function (ctx) {
const { type = "app" } = ctx.query const { type = "app" } = ctx.query
const response = await fetch( const response = await fetch(
`https://${DEFAULT_TEMPLATES_BUCKET}/manifest.json` `https://${DEFAULT_TEMPLATES_BUCKET}/manifest.json`
@ -16,7 +16,7 @@ exports.fetch = async function(ctx) {
// can't currently test this, have to ignore from coverage // can't currently test this, have to ignore from coverage
/* istanbul ignore next */ /* istanbul ignore next */
exports.downloadTemplate = async function(ctx) { exports.downloadTemplate = async function (ctx) {
const { type, name } = ctx.params const { type, name } = ctx.params
await downloadTemplate(type, name) await downloadTemplate(type, name)

View File

@ -13,7 +13,7 @@ const {
} = require("../../utilities/workerRequests") } = require("../../utilities/workerRequests")
const { getFullUser } = require("../../utilities/users") const { getFullUser } = require("../../utilities/users")
exports.fetchMetadata = async function(ctx) { exports.fetchMetadata = async function (ctx) {
const database = new CouchDB(ctx.appId) const database = new CouchDB(ctx.appId)
const global = await getGlobalUsers(ctx, ctx.appId) const global = await getGlobalUsers(ctx, ctx.appId)
const metadata = ( const metadata = (
@ -22,11 +22,11 @@ exports.fetchMetadata = async function(ctx) {
include_docs: true, include_docs: true,
}) })
) )
).rows.map(row => row.doc) ).rows.map((row) => row.doc)
const users = [] const users = []
for (let user of global) { for (let user of global) {
// find the metadata that matches up to the global ID // find the metadata that matches up to the global ID
const info = metadata.find(meta => meta._id.includes(user._id)) const info = metadata.find((meta) => meta._id.includes(user._id))
// remove these props, not for the correct DB // remove these props, not for the correct DB
users.push({ users.push({
...user, ...user,
@ -38,7 +38,7 @@ exports.fetchMetadata = async function(ctx) {
ctx.body = users ctx.body = users
} }
exports.createMetadata = async function(ctx) { exports.createMetadata = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const { roleId } = ctx.request.body const { roleId } = ctx.request.body
@ -70,7 +70,7 @@ exports.createMetadata = async function(ctx) {
} }
} }
exports.updateSelfMetadata = async function(ctx) { exports.updateSelfMetadata = async function (ctx) {
// overwrite the ID with current users // overwrite the ID with current users
ctx.request.body._id = ctx.user._id ctx.request.body._id = ctx.user._id
// make sure no stale rev // make sure no stale rev
@ -78,7 +78,7 @@ exports.updateSelfMetadata = async function(ctx) {
await exports.updateMetadata(ctx) await exports.updateMetadata(ctx)
} }
exports.updateMetadata = async function(ctx) { exports.updateMetadata = async function (ctx) {
const appId = ctx.appId const appId = ctx.appId
const db = new CouchDB(appId) const db = new CouchDB(appId)
const user = ctx.request.body const user = ctx.request.body
@ -94,7 +94,7 @@ exports.updateMetadata = async function(ctx) {
ctx.body = await db.put(metadata) ctx.body = await db.put(metadata)
} }
exports.destroyMetadata = async function(ctx) { exports.destroyMetadata = async function (ctx) {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
await deleteGlobalUser(ctx, getGlobalIDFromUserMetadataID(ctx.params.id)) await deleteGlobalUser(ctx, getGlobalIDFromUserMetadataID(ctx.params.id))
try { try {
@ -108,6 +108,6 @@ exports.destroyMetadata = async function(ctx) {
} }
} }
exports.findMetadata = async function(ctx) { exports.findMetadata = async function (ctx) {
ctx.body = await getFullUser(ctx, ctx.params.id) ctx.body = await getFullUser(ctx, ctx.params.id)
} }

Some files were not shown because too many files have changed in this diff Show More