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()}`
} }
@ -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)
} }

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

@ -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

@ -10,7 +10,7 @@ import {
} 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

@ -13,7 +13,7 @@ import {
} 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

@ -5,7 +5,7 @@ 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

@ -17,8 +17,8 @@ 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 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

@ -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
} }

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) {

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

@ -156,7 +156,7 @@ exports.fetch = async function(ctx) {
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) {

View File

@ -7,7 +7,7 @@ exports.fetchAppComponentDefinitions = async function(ctx) {
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

@ -13,7 +13,7 @@ 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) {
@ -38,7 +38,7 @@ exports.destroy = async function(ctx) {
// 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)

View File

@ -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

@ -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,7 +101,7 @@ 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
@ -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

View File

@ -35,7 +35,7 @@ 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) {

View File

@ -57,20 +57,20 @@ exports.fetch = async function(ctx) {
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))
} }
@ -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

@ -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

@ -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,
@ -303,7 +303,7 @@ 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)
} }
@ -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) {
@ -43,7 +43,7 @@ exports.uploadFile = async function(ctx) {
? 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}`

View File

@ -16,7 +16,7 @@ exports.fetch = async function(ctx) {
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) {
@ -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)

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

@ -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,

View File

@ -1,9 +1,9 @@
exports.csv = function (headers, rows) { exports.csv = function (headers, rows) {
let csv = headers.map(key => `"${key}"`).join(",") let csv = headers.map((key) => `"${key}"`).join(",")
for (let row of rows) { for (let row of rows) {
csv = `${csv}\n${headers csv = `${csv}\n${headers
.map(header => `"${row[header]}"`.trim()) .map((header) => `"${row[header]}"`.trim())
.join(",")}` .join(",")}`
} }
return csv return csv

View File

@ -6,7 +6,7 @@ const { fetchView } = require("../row")
const { ViewNames } = require("../../../db/utils") const { ViewNames } = require("../../../db/utils")
const controller = { const controller = {
fetch: async ctx => { fetch: async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const response = [] const response = []
@ -24,7 +24,7 @@ const controller = {
ctx.body = response ctx.body = response
}, },
save: async ctx => { save: async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const { originalName, ...viewToSave } = ctx.request.body const { originalName, ...viewToSave } = ctx.request.body
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
@ -65,7 +65,7 @@ const controller = {
name: viewToSave.name, name: viewToSave.name,
} }
}, },
destroy: async ctx => { destroy: async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const viewName = decodeURI(ctx.params.viewName) const viewName = decodeURI(ctx.params.viewName)
@ -80,7 +80,7 @@ const controller = {
ctx.body = view ctx.body = view
}, },
exportView: async ctx => { exportView: async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const designDoc = await db.get("_design/database") const designDoc = await db.get("_design/database")
const viewName = decodeURI(ctx.query.view) const viewName = decodeURI(ctx.query.view)

View File

@ -21,17 +21,17 @@ exports.WebhookType = {
AUTOMATION: "automation", AUTOMATION: "automation",
} }
exports.fetch = async ctx => { exports.fetch = async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const response = await db.allDocs( const response = await db.allDocs(
getWebhookParams(null, { getWebhookParams(null, {
include_docs: true, include_docs: true,
}) })
) )
ctx.body = response.rows.map(row => row.doc) ctx.body = response.rows.map((row) => row.doc)
} }
exports.save = async ctx => { exports.save = async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
const webhook = ctx.request.body const webhook = ctx.request.body
webhook.appId = ctx.appId webhook.appId = ctx.appId
@ -50,12 +50,12 @@ exports.save = async ctx => {
} }
} }
exports.destroy = async ctx => { exports.destroy = async (ctx) => {
const db = new CouchDB(ctx.appId) const db = new CouchDB(ctx.appId)
ctx.body = await db.remove(ctx.params.id, ctx.params.rev) ctx.body = await db.remove(ctx.params.id, ctx.params.rev)
} }
exports.buildSchema = async ctx => { exports.buildSchema = async (ctx) => {
const db = new CouchDB(ctx.params.instance) const db = new CouchDB(ctx.params.instance)
const webhook = await db.get(ctx.params.id) const webhook = await db.get(ctx.params.id)
webhook.bodySchema = toJsonSchema(ctx.request.body) webhook.bodySchema = toJsonSchema(ctx.request.body)
@ -75,7 +75,7 @@ exports.buildSchema = async ctx => {
ctx.body = await db.put(webhook) ctx.body = await db.put(webhook)
} }
exports.trigger = async ctx => { exports.trigger = async (ctx) => {
const db = new CouchDB(ctx.params.instance) const db = new CouchDB(ctx.params.instance)
const webhook = await db.get(ctx.params.id) const webhook = await db.get(ctx.params.id)
// validate against the schema // validate against the schema

View File

@ -36,8 +36,8 @@ router
} }
await next() await next()
}) })
.use("/health", ctx => (ctx.status = 200)) .use("/health", (ctx) => (ctx.status = 200))
.use("/version", ctx => (ctx.body = pkg.version)) .use("/version", (ctx) => (ctx.body = pkg.version))
.use(buildAuthMiddleware(NO_AUTH_ENDPOINTS)) .use(buildAuthMiddleware(NO_AUTH_ENDPOINTS))
.use(currentApp) .use(currentApp)
@ -58,7 +58,7 @@ router.use(async (ctx, next) => {
} }
}) })
router.get("/health", ctx => (ctx.status = 200)) router.get("/health", (ctx) => (ctx.status = 200))
// authenticated routes // authenticated routes
for (let route of mainRoutes) { for (let route of mainRoutes) {

View File

@ -7,7 +7,7 @@ function Request(appId, params) {
this.params = params this.params = params
} }
exports.getAllTableRows = async config => { exports.getAllTableRows = async (config) => {
const req = new Request(config.appId, { tableId: config.table._id }) const req = new Request(config.appId, { tableId: config.table._id })
await rowController.fetchTableRows(req) await rowController.fetchTableRows(req)
return req.body return req.body
@ -26,7 +26,7 @@ exports.clearAllApps = async () => {
} }
} }
exports.clearAllAutomations = async config => { exports.clearAllAutomations = async (config) => {
const automations = await config.getAllAutomations() const automations = await config.getAllAutomations()
for (let auto of automations) { for (let auto of automations) {
await config.deleteAutomation(auto) await config.deleteAutomation(auto)
@ -88,6 +88,6 @@ exports.checkPermissionsEndpoint = async ({
.expect(403) .expect(403)
} }
exports.getDB = config => { exports.getDB = (config) => {
return new CouchDB(config.getAppId()) return new CouchDB(config.getAppId())
} }

View File

@ -11,7 +11,7 @@ jest.mock("../../../../utilities/workerRequests", () => ({
}), }),
})) }))
exports.delay = ms => new Promise(resolve => setTimeout(resolve, ms)) exports.delay = (ms) => new Promise((resolve) => setTimeout(resolve, ms))
let request, config let request, config
@ -44,7 +44,7 @@ exports.getConfig = () => {
return config return config
} }
exports.switchToSelfHosted = async func => { exports.switchToSelfHosted = async (func) => {
// self hosted stops any attempts to Dynamo // self hosted stops any attempts to Dynamo
env._set("NODE_ENV", "production") env._set("NODE_ENV", "production")
env._set("SELF_HOSTED", true) env._set("SELF_HOSTED", true)

View File

@ -73,7 +73,7 @@ module.exports = server.listen(env.PORT || 0, async () => {
await automations.init() await automations.init()
}) })
process.on("uncaughtException", err => { process.on("uncaughtException", (err) => {
console.error(err) console.error(err)
server.close() server.close()
server.destroy() server.destroy()

View File

@ -9,7 +9,7 @@ let workers = workerFarm(require.resolve("./thread"))
function runWorker(job) { function runWorker(job) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
workers(job, err => { workers(job, (err) => {
if (err) { if (err) {
reject(err) reject(err)
} else { } else {
@ -32,7 +32,7 @@ async function updateQuota(automation) {
*/ */
module.exports.init = async function () { module.exports.init = async function () {
await actions.init() await actions.init()
triggers.automationQueue.process(async job => { triggers.automationQueue.process(async (job) => {
try { try {
if (env.USE_QUOTAS) { if (env.USE_QUOTAS) {
job.data.automation.apiKey = await updateQuota(job.data.automation) job.data.automation.apiKey = await updateQuota(job.data.automation)

View File

@ -17,7 +17,7 @@ exports.afterAll = () => {
config.end() config.end()
} }
exports.runInProd = async fn => { exports.runInProd = async (fn) => {
env._set("NODE_ENV", "production") env._set("NODE_ENV", "production")
env._set("USE_QUOTAS", 1) env._set("USE_QUOTAS", 1)
let error let error
@ -37,7 +37,7 @@ exports.runStep = async function runStep(stepId, inputs) {
let step let step
if ( if (
Object.values(exports.actions) Object.values(exports.actions)
.map(action => action.stepId) .map((action) => action.stepId)
.includes(stepId) .includes(stepId)
) { ) {
step = await actions.getAction(stepId) step = await actions.getAction(stepId)

View File

@ -204,8 +204,8 @@ async function queueRelevantRowAutomations(event, eventType) {
// filter down to the correct event type // filter down to the correct event type
automations = automations.rows automations = automations.rows
.map(automation => automation.doc) .map((automation) => automation.doc)
.filter(automation => { .filter((automation) => {
const trigger = automation.definition.trigger const trigger = automation.definition.trigger
return trigger && trigger.event === eventType return trigger && trigger.event === eventType
}) })

View File

@ -50,7 +50,7 @@ exports.createHomeScreen = () => ({
name: "home-screen", name: "home-screen",
}) })
exports.createLoginScreen = app => ({ exports.createLoginScreen = (app) => ({
description: "", description: "",
url: "", url: "",
layoutId: BASE_LAYOUT_PROP_IDS.PUBLIC, layoutId: BASE_LAYOUT_PROP_IDS.PUBLIC,

View File

@ -27,7 +27,7 @@ exports.getBuilderMainDoc = async () => {
} }
} }
exports.setBuilderMainDoc = async doc => { exports.setBuilderMainDoc = async (doc) => {
if (!env.SELF_HOSTED) { if (!env.SELF_HOSTED) {
throw SELF_HOST_ERR throw SELF_HOST_ERR
} }

View File

@ -31,7 +31,7 @@ allDbs(Pouch)
/* istanbul ignore next */ /* istanbul ignore next */
// eslint-disable-next-line no-unused-vars // eslint-disable-next-line no-unused-vars
function replicateLocal() { function replicateLocal() {
Pouch.allDbs().then(dbs => { Pouch.allDbs().then((dbs) => {
for (let db of dbs) { for (let db of dbs) {
new Pouch(db).sync( new Pouch(db).sync(
new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true }) new PouchDB(`http://127.0.0.1:5984/${db}`, { live: true })

View File

@ -100,7 +100,7 @@ class Table {
} }
} }
exports.init = endpoint => { exports.init = (endpoint) => {
let AWS = require("aws-sdk") let AWS = require("aws-sdk")
AWS.config.update({ AWS.config.update({
region: AWS_REGION, region: AWS_REGION,

View File

@ -194,11 +194,11 @@ class LinkController {
if (field.type === FieldTypes.LINK && rowField != null) { if (field.type === FieldTypes.LINK && rowField != null) {
// check which links actual pertain to the update in this row // check which links actual pertain to the update in this row
const thisFieldLinkDocs = linkDocs.filter( const thisFieldLinkDocs = linkDocs.filter(
linkDoc => (linkDoc) =>
linkDoc.doc1.fieldName === fieldName || linkDoc.doc1.fieldName === fieldName ||
linkDoc.doc2.fieldName === fieldName linkDoc.doc2.fieldName === fieldName
) )
const linkDocIds = thisFieldLinkDocs.map(linkDoc => { const linkDocIds = thisFieldLinkDocs.map((linkDoc) => {
return linkDoc.doc1.rowId === row._id return linkDoc.doc1.rowId === row._id
? linkDoc.doc2.rowId ? linkDoc.doc2.rowId
: linkDoc.doc1.rowId : linkDoc.doc1.rowId
@ -218,7 +218,7 @@ class LinkController {
rowId: linkId, rowId: linkId,
includeDocs: IncludeDocs.EXCLUDE, includeDocs: IncludeDocs.EXCLUDE,
}) })
).filter(link => link.id !== row._id) ).filter((link) => link.id !== row._id)
// The 1 side of 1:N is already related to something else // The 1 side of 1:N is already related to something else
// You must remove the existing relationship // You must remove the existing relationship
@ -251,12 +251,12 @@ class LinkController {
} }
// find the docs that need to be deleted // find the docs that need to be deleted
let toDeleteDocs = thisFieldLinkDocs let toDeleteDocs = thisFieldLinkDocs
.filter(doc => { .filter((doc) => {
let correctDoc = let correctDoc =
doc.doc1.fieldName === fieldName ? doc.doc2 : doc.doc1 doc.doc1.fieldName === fieldName ? doc.doc2 : doc.doc1
return rowField.indexOf(correctDoc.rowId) === -1 return rowField.indexOf(correctDoc.rowId) === -1
}) })
.map(doc => { .map((doc) => {
return { ...doc, _deleted: true } return { ...doc, _deleted: true }
}) })
// now add the docs to be deleted to the bulk operation // now add the docs to be deleted to the bulk operation
@ -282,7 +282,7 @@ class LinkController {
if (linkDocs.length === 0) { if (linkDocs.length === 0) {
return null return null
} }
const toDelete = linkDocs.map(doc => { const toDelete = linkDocs.map((doc) => {
return { return {
...doc, ...doc,
_deleted: true, _deleted: true,
@ -301,7 +301,7 @@ class LinkController {
let oldTable = this._oldTable let oldTable = this._oldTable
let field = oldTable.schema[fieldName] let field = oldTable.schema[fieldName]
const linkDocs = await this.getTableLinkDocs() const linkDocs = await this.getTableLinkDocs()
let toDelete = linkDocs.filter(linkDoc => { let toDelete = linkDocs.filter((linkDoc) => {
let correctFieldName = let correctFieldName =
linkDoc.doc1.tableId === oldTable._id linkDoc.doc1.tableId === oldTable._id
? linkDoc.doc1.fieldName ? linkDoc.doc1.fieldName
@ -309,7 +309,7 @@ class LinkController {
return correctFieldName === fieldName return correctFieldName === fieldName
}) })
await this._db.bulkDocs( await this._db.bulkDocs(
toDelete.map(doc => { toDelete.map((doc) => {
return { return {
...doc, ...doc,
_deleted: true, _deleted: true,
@ -434,7 +434,7 @@ class LinkController {
return null return null
} }
// get link docs for this table and configure for deletion // get link docs for this table and configure for deletion
const toDelete = linkDocs.map(doc => { const toDelete = linkDocs.map((doc) => {
return { return {
...doc, ...doc,
_deleted: true, _deleted: true,

View File

@ -33,11 +33,11 @@ exports.getLinkDocuments = getLinkDocuments
exports.createLinkView = createLinkView exports.createLinkView = createLinkView
async function getLinksForRows(appId, rows) { async function getLinksForRows(appId, rows) {
const tableIds = [...new Set(rows.map(el => el.tableId))] const tableIds = [...new Set(rows.map((el) => el.tableId))]
// start by getting all the link values for performance reasons // start by getting all the link values for performance reasons
const responses = flatten( const responses = flatten(
await Promise.all( await Promise.all(
tableIds.map(tableId => tableIds.map((tableId) =>
getLinkDocuments({ getLinkDocuments({
appId, appId,
tableId: tableId, tableId: tableId,
@ -51,7 +51,7 @@ async function getLinksForRows(appId, rows) {
return getUniqueByProp( return getUniqueByProp(
responses responses
// create a unique ID which we can use for getting only unique ones // create a unique ID which we can use for getting only unique ones
.map(el => ({ ...el, unique: el.id + el.thisId + el.fieldName })), .map((el) => ({ ...el, unique: el.id + el.thisId + el.fieldName })),
"unique" "unique"
) )
} }
@ -127,8 +127,8 @@ exports.attachLinkIDs = async (appId, rows) => {
for (let row of rows) { for (let row of rows) {
// find anything that matches the row's ID we are searching for and join it // find anything that matches the row's ID we are searching for and join it
links links
.filter(el => el.thisId === row._id) .filter((el) => el.thisId === row._id)
.forEach(link => { .forEach((link) => {
if (row[link.fieldName] == null) { if (row[link.fieldName] == null) {
row[link.fieldName] = [] row[link.fieldName] = []
} }
@ -154,21 +154,21 @@ exports.attachLinkedPrimaryDisplay = async (appId, table, rows) => {
return rows return rows
} }
const db = new CouchDB(appId) const db = new CouchDB(appId)
const links = (await getLinksForRows(appId, rows)).filter(link => const links = (await getLinksForRows(appId, rows)).filter((link) =>
rows.some(row => row._id === link.thisId) rows.some((row) => row._id === link.thisId)
) )
const linkedRowIds = links.map(link => link.id) const linkedRowIds = links.map((link) => link.id)
const linked = (await db.allDocs(getMultiIDParams(linkedRowIds))).rows.map( const linked = (await db.allDocs(getMultiIDParams(linkedRowIds))).rows.map(
row => row.doc (row) => row.doc
) )
// will populate this as we find them // will populate this as we find them
const linkedTables = [] const linkedTables = []
for (let row of rows) { for (let row of rows) {
for (let link of links.filter(link => link.thisId === row._id)) { for (let link of links.filter((link) => link.thisId === row._id)) {
if (row[link.fieldName] == null) { if (row[link.fieldName] == null) {
row[link.fieldName] = [] row[link.fieldName] = []
} }
const linkedRow = linked.find(row => row._id === link.id) const linkedRow = linked.find((row) => row._id === link.id)
const linkedTableId = const linkedTableId =
linkedRow.tableId || getRelatedTableForField(table, link.fieldName) linkedRow.tableId || getRelatedTableForField(table, link.fieldName)
const linkedTable = await getLinkedTable(db, linkedTableId, linkedTables) const linkedTable = await getLinkedTable(db, linkedTableId, linkedTables)

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