diff --git a/packages/backend-core/src/migrations/migrations.ts b/packages/backend-core/src/migrations/migrations.ts index 60c17f4020..7bc2dec290 100644 --- a/packages/backend-core/src/migrations/migrations.ts +++ b/packages/backend-core/src/migrations/migrations.ts @@ -1,10 +1,13 @@ import { DEFAULT_TENANT_ID } from "../constants" -import { doWithDB } from "../db" -import { DocumentType, StaticDatabases } from "../db/constants" -import { getAllApps } from "../db/utils" +import { + DocumentType, + StaticDatabases, + getAllApps, + getGlobalDBName, + doWithDB, +} from "../db" import environment from "../environment" import { doInTenant, getTenantIds, getTenantId } from "../tenancy" -import { getGlobalDBName } from "../db/tenancy" import * as context from "../context" import { DEFINITIONS } from "." import { diff --git a/packages/server/scripts/exportAppTemplate.js b/packages/server/scripts/exportAppTemplate.js index bb1de425ba..04688b071f 100755 --- a/packages/server/scripts/exportAppTemplate.js +++ b/packages/server/scripts/exportAppTemplate.js @@ -3,7 +3,7 @@ const yargs = require("yargs") const fs = require("fs") const { join } = require("path") require("../src/db").init() -const { doWithDB } = require("@budibase/backend-core/db") +const { db: dbCore } = require("@budibase/backend-core") // load environment const env = require("../src/environment") const { @@ -48,7 +48,7 @@ yargs const writeStream = fs.createWriteStream(join(exportPath, "dump.text")) // perform couch dump - await doWithDB(appId, async db => { + await dbCore.doWithDB(appId, async db => { return db.dump(writeStream, { filter: doc => !( diff --git a/packages/server/src/api/controllers/auth.ts b/packages/server/src/api/controllers/auth.ts index 88dc581020..c28b99529b 100644 --- a/packages/server/src/api/controllers/auth.ts +++ b/packages/server/src/api/controllers/auth.ts @@ -3,7 +3,7 @@ import { InternalTables } from "../../db/utils" import { getFullUser } from "../../utilities/users" import { roles, context } from "@budibase/backend-core" import { groups } from "@budibase/pro" -import { ContextUser, User } from "@budibase/types" +import { ContextUser, User, Row } from "@budibase/types" const PUBLIC_ROLE = roles.BUILTIN_ROLE_IDS.PUBLIC @@ -43,7 +43,7 @@ export async function fetchSelf(ctx: any) { try { const userTable = await db.get(InternalTables.USER_METADATA) // specifically needs to make sure is enriched - ctx.body = await outputProcessing(userTable, user) + ctx.body = await outputProcessing(userTable, user as Row) } catch (err: any) { let response // user didn't exist in app, don't pretend they do diff --git a/packages/server/src/api/controllers/cloud.ts b/packages/server/src/api/controllers/cloud.ts index 7f29369bf2..41c21d534a 100644 --- a/packages/server/src/api/controllers/cloud.ts +++ b/packages/server/src/api/controllers/cloud.ts @@ -7,7 +7,6 @@ import { create } from "./application" import { join } from "path" import { App, BBContext, Database } from "@budibase/types" import sdk from "../../sdk" -import { getAllApps } from "@budibase/backend-core/src/db" async function createApp(appName: string, appDirectory: string) { const ctx = { @@ -39,7 +38,7 @@ export async function exportApps(ctx: BBContext) { if (env.SELF_HOSTED || !env.MULTI_TENANCY) { ctx.throw(400, "Exporting only allowed in multi-tenant cloud environments.") } - const apps = (await getAllApps({ all: true })) as App[] + const apps = (await dbCore.getAllApps({ all: true })) as App[] const globalDBString = await sdk.backups.exportDB(dbCore.getGlobalDBName(), { filter: (doc: any) => !doc._id.startsWith(DocumentType.USER), }) @@ -61,7 +60,7 @@ async function checkHasBeenImported() { if (!env.SELF_HOSTED || env.MULTI_TENANCY) { return true } - const apps = await getAllApps({ all: true }) + const apps = await dbCore.getAllApps({ all: true }) return apps.length !== 0 } diff --git a/packages/server/src/api/controllers/datasource.js b/packages/server/src/api/controllers/datasource.ts similarity index 74% rename from packages/server/src/api/controllers/datasource.js rename to packages/server/src/api/controllers/datasource.ts index 80bd263d87..511eb8ab74 100644 --- a/packages/server/src/api/controllers/datasource.js +++ b/packages/server/src/api/controllers/datasource.ts @@ -1,30 +1,29 @@ -const { +import { generateDatasourceID, getDatasourceParams, getQueryParams, DocumentType, BudibaseInternalDB, getTableParams, -} = require("../../db/utils") -const { destroy: tableDestroy } = require("./table/internal") -const { BuildSchemaErrors, InvalidColumns } = require("../../constants") -const { getIntegration } = require("../../integrations") -const { getDatasourceAndQuery } = require("./row/utils") -const { invalidateDynamicVariables } = require("../../threads/utils") -const { getAppDB } = require("@budibase/backend-core/context") -const { events } = require("@budibase/backend-core") -const { db: dbCore } = require("@budibase/backend-core") +} from "../../db/utils" +import { destroy as tableDestroy } from "./table/internal" +import { BuildSchemaErrors, InvalidColumns } from "../../constants" +import { getIntegration } from "../../integrations" +import { getDatasourceAndQuery } from "./row/utils" +import { invalidateDynamicVariables } from "../../threads/utils" +import { db as dbCore, context, events } from "@budibase/backend-core" +import { BBContext, Datasource, Row } from "@budibase/types" -exports.fetch = async function (ctx) { +export async function fetch(ctx: BBContext) { // Get internal tables - const db = getAppDB() + const db = context.getAppDB() const internalTables = await db.allDocs( getTableParams(null, { include_docs: true, }) ) - const internal = internalTables.rows.reduce((acc, row) => { + const internal = internalTables.rows.reduce((acc: any, row: Row) => { const sourceId = row.doc.sourceId || "bb_internal" acc[sourceId] = acc[sourceId] || [] acc[sourceId].push(row.doc) @@ -60,8 +59,8 @@ exports.fetch = async function (ctx) { ctx.body = [bbInternalDb, ...datasources] } -exports.buildSchemaFromDb = async function (ctx) { - const db = getAppDB() +export async function buildSchemaFromDb(ctx: BBContext) { + const db = context.getAppDB() const datasource = await db.get(ctx.params.datasourceId) const tablesFilter = ctx.request.body.tablesFilter @@ -72,7 +71,9 @@ exports.buildSchemaFromDb = async function (ctx) { } for (let key in tables) { if ( - tablesFilter.some(filter => filter.toLowerCase() === key.toLowerCase()) + tablesFilter.some( + (filter: any) => filter.toLowerCase() === key.toLowerCase() + ) ) { datasource.entities[key] = tables[key] } @@ -85,7 +86,7 @@ exports.buildSchemaFromDb = async function (ctx) { const dbResp = await db.put(datasource) datasource._rev = dbResp.rev - const response = { datasource } + const response: any = { datasource } if (error) { response.error = error } @@ -95,9 +96,9 @@ exports.buildSchemaFromDb = async function (ctx) { /** * Make sure all datasource entities have a display name selected */ -const setDefaultDisplayColumns = datasource => { +function setDefaultDisplayColumns(datasource: Datasource) { // - for (let entity of Object.values(datasource.entities)) { + for (let entity of Object.values(datasource.entities || {})) { if (entity.primaryDisplay) { continue } @@ -113,9 +114,12 @@ const setDefaultDisplayColumns = datasource => { /** * Check for variables that have been updated or removed and invalidate them. */ -const invalidateVariables = async (existingDatasource, updatedDatasource) => { - const existingVariables = existingDatasource.config.dynamicVariables - const updatedVariables = updatedDatasource.config.dynamicVariables +async function invalidateVariables( + existingDatasource: Datasource, + updatedDatasource: Datasource +) { + const existingVariables: any = existingDatasource.config?.dynamicVariables + const updatedVariables: any = updatedDatasource.config?.dynamicVariables const toInvalidate = [] if (!existingVariables) { @@ -127,9 +131,9 @@ const invalidateVariables = async (existingDatasource, updatedDatasource) => { toInvalidate.push(...existingVariables) } else { // invaldate changed / removed - existingVariables.forEach(existing => { + existingVariables.forEach((existing: any) => { const unchanged = updatedVariables.find( - updated => + (updated: any) => existing.name === updated.name && existing.queryId === updated.queryId && existing.value === updated.value @@ -142,8 +146,8 @@ const invalidateVariables = async (existingDatasource, updatedDatasource) => { await invalidateDynamicVariables(toInvalidate) } -exports.update = async function (ctx) { - const db = getAppDB() +export async function update(ctx: BBContext) { + const db = context.getAppDB() const datasourceId = ctx.params.datasourceId let datasource = await db.get(datasourceId) const auth = datasource.config.auth @@ -171,8 +175,8 @@ exports.update = async function (ctx) { ctx.body = { datasource } } -exports.save = async function (ctx) { - const db = getAppDB() +export async function save(ctx: BBContext) { + const db = context.getAppDB() const plus = ctx.request.body.datasource.plus const fetchSchema = ctx.request.body.fetchSchema @@ -202,15 +206,15 @@ exports.save = async function (ctx) { } } - const response = { datasource } + const response: any = { datasource } if (schemaError) { response.error = schemaError } ctx.body = response } -const destroyInternalTablesBySourceId = async datasourceId => { - const db = getAppDB() +async function destroyInternalTablesBySourceId(datasourceId: string) { + const db = context.getAppDB() // Get all internal tables const internalTables = await db.allDocs( @@ -220,12 +224,15 @@ const destroyInternalTablesBySourceId = async datasourceId => { ) // Filter by datasource and return the docs. - const datasourceTableDocs = internalTables.rows.reduce((acc, table) => { - if (table.doc.sourceId == datasourceId) { - acc.push(table.doc) - } - return acc - }, []) + const datasourceTableDocs = internalTables.rows.reduce( + (acc: any, table: any) => { + if (table.doc.sourceId == datasourceId) { + acc.push(table.doc) + } + return acc + }, + [] + ) // Destroy the tables. for (const table of datasourceTableDocs) { @@ -237,8 +244,8 @@ const destroyInternalTablesBySourceId = async datasourceId => { } } -exports.destroy = async function (ctx) { - const db = getAppDB() +export async function destroy(ctx: BBContext) { + const db = context.getAppDB() const datasourceId = ctx.params.datasourceId const datasource = await db.get(datasourceId) @@ -249,7 +256,7 @@ exports.destroy = async function (ctx) { } else { const queries = await db.allDocs(getQueryParams(datasourceId, null)) await db.bulkDocs( - queries.rows.map(row => ({ + queries.rows.map((row: any) => ({ _id: row.id, _rev: row.value.rev, _deleted: true, @@ -265,28 +272,28 @@ exports.destroy = async function (ctx) { ctx.status = 200 } -exports.find = async function (ctx) { - const database = getAppDB() +export async function find(ctx: BBContext) { + const database = context.getAppDB() ctx.body = await database.get(ctx.params.datasourceId) } // dynamic query functionality -exports.query = async function (ctx) { +export async function query(ctx: BBContext) { const queryJson = ctx.request.body try { ctx.body = await getDatasourceAndQuery(queryJson) - } catch (err) { + } catch (err: any) { ctx.throw(400, err) } } -function getErrorTables(errors, errorType) { +function getErrorTables(errors: any, errorType: string) { return Object.entries(errors) .filter(entry => entry[1] === errorType) .map(([name]) => name) } -function updateError(error, newError, tables) { +function updateError(error: any, newError: any, tables: string[]) { if (!error) { error = "" } @@ -297,7 +304,7 @@ function updateError(error, newError, tables) { return error } -const buildSchemaHelper = async datasource => { +async function buildSchemaHelper(datasource: Datasource) { const Connector = await getIntegration(datasource.source) // Connect to the DB and build the schema diff --git a/packages/server/src/api/controllers/deploy/Deployment.ts b/packages/server/src/api/controllers/deploy/Deployment.ts index 765f22acc1..c15cffbcd8 100644 --- a/packages/server/src/api/controllers/deploy/Deployment.ts +++ b/packages/server/src/api/controllers/deploy/Deployment.ts @@ -4,7 +4,7 @@ import { context } from "@budibase/backend-core" /** * This is used to pass around information about the deployment that is occurring */ -export class Deployment { +export default class Deployment { _id: string verification: any status?: string diff --git a/packages/server/src/api/controllers/layout.js b/packages/server/src/api/controllers/layout.ts similarity index 70% rename from packages/server/src/api/controllers/layout.js rename to packages/server/src/api/controllers/layout.ts index f3f52d4ef0..c00252d643 100644 --- a/packages/server/src/api/controllers/layout.js +++ b/packages/server/src/api/controllers/layout.ts @@ -1,10 +1,10 @@ -const { EMPTY_LAYOUT } = require("../../constants/layouts") -const { generateLayoutID, getScreenParams } = require("../../db/utils") -const { getAppDB } = require("@budibase/backend-core/context") -const { events } = require("@budibase/backend-core") +import { EMPTY_LAYOUT } from "../../constants/layouts" +import { generateLayoutID, getScreenParams } from "../../db/utils" +import { events, context } from "@budibase/backend-core" +import { BBContext } from "@budibase/types" -exports.save = async function (ctx) { - const db = getAppDB() +export async function save(ctx: BBContext) { + const db = context.getAppDB() let layout = ctx.request.body if (!layout.props) { @@ -24,8 +24,8 @@ exports.save = async function (ctx) { ctx.status = 200 } -exports.destroy = async function (ctx) { - const db = getAppDB() +export async function destroy(ctx: BBContext) { + const db = context.getAppDB() const layoutId = ctx.params.layoutId, layoutRev = ctx.params.layoutRev diff --git a/packages/server/src/api/controllers/public/tables.ts b/packages/server/src/api/controllers/public/tables.ts index 3ee94bddb3..a346a750da 100644 --- a/packages/server/src/api/controllers/public/tables.ts +++ b/packages/server/src/api/controllers/public/tables.ts @@ -1,6 +1,6 @@ import { search as stringSearch, addRev } from "./utils" -import { default as controller } from "../table" -import { Table } from "../../../definitions/common" +import * as controller from "../table" +import { Table } from "@budibase/types" function fixTable(table: Table, params: any) { if (!params || !table) { diff --git a/packages/server/src/api/controllers/row/external.js b/packages/server/src/api/controllers/row/external.js index fa48106d26..e0c3a9ee4d 100644 --- a/packages/server/src/api/controllers/row/external.js +++ b/packages/server/src/api/controllers/row/external.js @@ -9,7 +9,7 @@ const { breakRowIdField, } = require("../../../integrations/utils") const ExternalRequest = require("./ExternalRequest") -const { getAppDB } = require("@budibase/backend-core/context") +const { context } = require("@budibase/backend-core") const exporters = require("../view/exporters") const { apiFileReturn } = require("../../../utilities/fileSystem") @@ -166,7 +166,7 @@ exports.validate = async () => { exports.exportRows = async ctx => { const { datasourceId } = breakExternalTableId(ctx.params.tableId) - const db = getAppDB() + const db = context.getAppDB() const format = ctx.query.format const { columns } = ctx.request.body const datasource = await db.get(datasourceId) @@ -209,7 +209,7 @@ exports.fetchEnrichedRow = async ctx => { const id = ctx.params.rowId const tableId = ctx.params.tableId const { datasourceId, tableName } = breakExternalTableId(tableId) - const db = getAppDB() + const db = context.getAppDB() const datasource = await db.get(datasourceId) if (!datasource || !datasource.entities) { ctx.throw(400, "Datasource has not been configured for plus API.") diff --git a/packages/server/src/api/controllers/row/internal.js b/packages/server/src/api/controllers/row/internal.js index 0f1324f10e..9b105fd3ae 100644 --- a/packages/server/src/api/controllers/row/internal.js +++ b/packages/server/src/api/controllers/row/internal.js @@ -6,7 +6,6 @@ const { DocumentType, InternalTables, } = require("../../../db/utils") -const { getDB } = require("@budibase/backend-core/db") const userController = require("../user") const { inputProcessing, @@ -26,7 +25,7 @@ const { getFromMemoryDoc, } = require("../view/utils") const { cloneDeep } = require("lodash/fp") -const { getAppDB } = require("@budibase/backend-core/context") +const { context, db: dbCore } = require("@budibase/backend-core") const { finaliseRow, updateRelatedFormula } = require("./staticFormula") const exporters = require("../view/exporters") const { apiFileReturn } = require("../../../utilities/fileSystem") @@ -80,7 +79,7 @@ async function getRawTableData(ctx, db, tableId) { } exports.patch = async ctx => { - const db = getAppDB() + const db = context.getAppDB() const inputs = ctx.request.body const tableId = inputs.tableId const isUserTable = tableId === InternalTables.USER_METADATA @@ -145,7 +144,7 @@ exports.patch = async ctx => { } exports.save = async function (ctx) { - const db = getAppDB() + const db = context.getAppDB() let inputs = ctx.request.body inputs.tableId = ctx.params.tableId @@ -188,7 +187,7 @@ exports.fetchView = async ctx => { return exports.fetch(ctx) } - const db = getAppDB() + const db = context.getAppDB() const { calculation, group, field } = ctx.query const viewInfo = await getView(db, viewName) let response @@ -242,7 +241,7 @@ exports.fetchView = async ctx => { } exports.fetch = async ctx => { - const db = getAppDB() + const db = context.getAppDB() const tableId = ctx.params.tableId let table = await db.get(tableId) @@ -251,7 +250,7 @@ exports.fetch = async ctx => { } exports.find = async ctx => { - const db = getDB(ctx.appId) + const db = dbCore.getDB(ctx.appId) const table = await db.get(ctx.params.tableId) let row = await findRow(ctx, ctx.params.tableId, ctx.params.rowId) row = await outputProcessing(table, row) @@ -259,7 +258,7 @@ exports.find = async ctx => { } exports.destroy = async function (ctx) { - const db = getAppDB() + const db = context.getAppDB() const { _id } = ctx.request.body let row = await db.get(_id) let _rev = ctx.request.body._rev || row._rev @@ -295,7 +294,7 @@ exports.destroy = async function (ctx) { } exports.bulkDestroy = async ctx => { - const db = getAppDB() + const db = context.getAppDB() const tableId = ctx.params.tableId const table = await db.get(tableId) let { rows } = ctx.request.body @@ -338,7 +337,7 @@ exports.search = async ctx => { } const { tableId } = ctx.params - const db = getAppDB() + const db = context.getAppDB() const { paginate, query, ...params } = ctx.request.body params.version = ctx.version params.tableId = tableId @@ -371,7 +370,7 @@ exports.validate = async ctx => { } exports.exportRows = async ctx => { - const db = getAppDB() + const db = context.getAppDB() const table = await db.get(ctx.params.tableId) const rowIds = ctx.request.body.rows let format = ctx.query.format @@ -408,7 +407,7 @@ exports.exportRows = async ctx => { } exports.fetchEnrichedRow = async ctx => { - const db = getAppDB() + const db = context.getAppDB() const tableId = ctx.params.tableId const rowId = ctx.params.rowId // need table to work out where links go in row diff --git a/packages/server/src/api/controllers/row/utils.ts b/packages/server/src/api/controllers/row/utils.ts index eea80a3cd8..3719c206e2 100644 --- a/packages/server/src/api/controllers/row/utils.ts +++ b/packages/server/src/api/controllers/row/utils.ts @@ -1,5 +1,5 @@ import { InternalTables } from "../../../db/utils" -import userController from "../user" +import * as userController from "../user" import { FieldTypes } from "../../../constants" import { context } from "@budibase/backend-core" import { makeExternalQuery } from "../../../integrations/base/query" diff --git a/packages/server/src/api/controllers/table/internal.ts b/packages/server/src/api/controllers/table/internal.ts index 9b2f20497b..a70ba4dcba 100644 --- a/packages/server/src/api/controllers/table/internal.ts +++ b/packages/server/src/api/controllers/table/internal.ts @@ -133,7 +133,7 @@ export async function save(ctx: any) { tableToSave._rev = result.rev } // has to run after, make sure it has _id - await runStaticFormulaChecks(tableToSave, { oldTable, deletion: null }) + await runStaticFormulaChecks(tableToSave, { oldTable, deletion: false }) return tableToSave } @@ -176,7 +176,6 @@ export async function destroy(ctx: any) { // has to run after, make sure it has _id await runStaticFormulaChecks(tableToDelete, { - oldTable: null, deletion: true, }) await cleanupAttachments(tableToDelete, { diff --git a/packages/server/src/api/controllers/user.js b/packages/server/src/api/controllers/user.ts similarity index 69% rename from packages/server/src/api/controllers/user.js rename to packages/server/src/api/controllers/user.ts index 7d4ef65994..f1a66f2c19 100644 --- a/packages/server/src/api/controllers/user.js +++ b/packages/server/src/api/controllers/user.ts @@ -1,23 +1,22 @@ -const { +import { generateUserMetadataID, getUserMetadataParams, generateUserFlagID, -} = require("../../db/utils") -const { InternalTables } = require("../../db/utils") -const { getGlobalUsers, getRawGlobalUser } = require("../../utilities/global") -const { getFullUser } = require("../../utilities/users") -const { isEqual } = require("lodash") -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") -const { - getDevelopmentAppID, - getProdAppIDs, - dbExists, -} = require("@budibase/backend-core/db") -const { UserStatus } = require("@budibase/backend-core/constants") -const { getAppDB, doInAppContext } = require("@budibase/backend-core/context") +} from "../../db/utils" +import { InternalTables } from "../../db/utils" +import { getGlobalUsers, getRawGlobalUser } from "../../utilities/global" +import { getFullUser } from "../../utilities/users" +import { isEqual } from "lodash" +import { + context, + constants, + roles as rolesCore, + db as dbCore, +} from "@budibase/backend-core" +import { BBContext, User } from "@budibase/types" async function rawMetadata() { - const db = getAppDB() + const db = context.getAppDB() return ( await db.allDocs( getUserMetadataParams(null, { @@ -27,9 +26,9 @@ async function rawMetadata() { ).rows.map(row => row.doc) } -function combineMetadataAndUser(user, metadata) { +function combineMetadataAndUser(user: any, metadata: any) { // skip users with no access - if (user.roleId === BUILTIN_ROLE_IDS.PUBLIC) { + if (user.roleId === rolesCore.BUILTIN_ROLE_IDS.PUBLIC) { return null } delete user._rev @@ -55,9 +54,9 @@ function combineMetadataAndUser(user, metadata) { return null } -exports.syncGlobalUsers = async () => { +export async function syncGlobalUsers() { // sync user metadata - const db = getAppDB() + const db = context.getAppDB() const [users, metadata] = await Promise.all([getGlobalUsers(), rawMetadata()]) const toWrite = [] for (let user of users) { @@ -69,13 +68,13 @@ exports.syncGlobalUsers = async () => { await db.bulkDocs(toWrite) } -exports.syncUser = async function (ctx) { +export async function syncUser(ctx: BBContext) { let deleting = false, - user + user: User | any const userId = ctx.params.id try { user = await getRawGlobalUser(userId) - } catch (err) { + } catch (err: any) { if (err && err.status === 404) { user = {} deleting = true @@ -92,21 +91,21 @@ exports.syncUser = async function (ctx) { let prodAppIds // if they are a builder then get all production app IDs if ((user.builder && user.builder.global) || deleting) { - prodAppIds = await getProdAppIDs() + prodAppIds = await dbCore.getProdAppIDs() } else { prodAppIds = Object.entries(roles) - .filter(entry => entry[1] !== BUILTIN_ROLE_IDS.PUBLIC) + .filter(entry => entry[1] !== rolesCore.BUILTIN_ROLE_IDS.PUBLIC) .map(([appId]) => appId) } for (let prodAppId of prodAppIds) { const roleId = roles[prodAppId] - const devAppId = getDevelopmentAppID(prodAppId) + const devAppId = dbCore.getDevelopmentAppID(prodAppId) for (let appId of [prodAppId, devAppId]) { - if (!(await dbExists(appId))) { + if (!(await dbCore.dbExists(appId))) { continue } - await doInAppContext(appId, async () => { - const db = getAppDB() + await context.doInAppContext(appId, async () => { + const db = context.getAppDB() const metadataId = generateUserMetadataID(userId) let metadata try { @@ -127,8 +126,8 @@ exports.syncUser = async function (ctx) { ? combineMetadataAndUser(user, metadata) : { ...metadata, - status: UserStatus.INACTIVE, - metadata: BUILTIN_ROLE_IDS.PUBLIC, + status: constants.UserStatus.INACTIVE, + metadata: rolesCore.BUILTIN_ROLE_IDS.PUBLIC, } // if its null then there was no updates required if (combined) { @@ -142,10 +141,9 @@ exports.syncUser = async function (ctx) { } } -exports.fetchMetadata = async function (ctx) { - const database = getAppDB() +export async function fetchMetadata(ctx: BBContext) { const global = await getGlobalUsers() - const metadata = await rawMetadata(database) + const metadata = await rawMetadata() const users = [] for (let user of global) { // find the metadata that matches up to the global ID @@ -162,18 +160,18 @@ exports.fetchMetadata = async function (ctx) { ctx.body = users } -exports.updateSelfMetadata = async function (ctx) { +export async function updateSelfMetadata(ctx: BBContext) { // overwrite the ID with current users - ctx.request.body._id = ctx.user._id + ctx.request.body._id = ctx.user?._id // make sure no stale rev delete ctx.request.body._rev // make sure no csrf token delete ctx.request.body.csrfToken - await exports.updateMetadata(ctx) + await updateMetadata(ctx) } -exports.updateMetadata = async function (ctx) { - const db = getAppDB() +export async function updateMetadata(ctx: BBContext) { + const db = context.getAppDB() const user = ctx.request.body // this isn't applicable to the user delete user.roles @@ -184,8 +182,8 @@ exports.updateMetadata = async function (ctx) { ctx.body = await db.put(metadata) } -exports.destroyMetadata = async function (ctx) { - const db = getAppDB() +export async function destroyMetadata(ctx: BBContext) { + const db = context.getAppDB() try { const dbUser = await db.get(ctx.params.id) await db.remove(dbUser._id, dbUser._rev) @@ -197,18 +195,18 @@ exports.destroyMetadata = async function (ctx) { } } -exports.findMetadata = async function (ctx) { +export async function findMetadata(ctx: BBContext) { ctx.body = await getFullUser(ctx, ctx.params.id) } -exports.setFlag = async function (ctx) { - const userId = ctx.user._id +export async function setFlag(ctx: BBContext) { + const userId = ctx.user?._id const { flag, value } = ctx.request.body if (!flag) { ctx.throw(400, "Must supply a 'flag' field in request body.") } - const flagDocId = generateUserFlagID(userId) - const db = getAppDB() + const flagDocId = generateUserFlagID(userId!) + const db = context.getAppDB() let doc try { doc = await db.get(flagDocId) @@ -220,10 +218,10 @@ exports.setFlag = async function (ctx) { ctx.body = { message: "Flag set successfully" } } -exports.getFlags = async function (ctx) { - const userId = ctx.user._id - const docId = generateUserFlagID(userId) - const db = getAppDB() +export async function getFlags(ctx: BBContext) { + const userId = ctx.user?._id + const docId = generateUserFlagID(userId!) + const db = context.getAppDB() let doc try { doc = await db.get(docId) diff --git a/packages/server/src/api/controllers/view/utils.ts b/packages/server/src/api/controllers/view/utils.ts index 7fa37e6c5d..ef7ce772f9 100644 --- a/packages/server/src/api/controllers/view/utils.ts +++ b/packages/server/src/api/controllers/view/utils.ts @@ -70,7 +70,7 @@ export async function getViews() { } export async function saveView( - originalName: string, + originalName: string | null, viewName: string, viewTemplate: any ) { diff --git a/packages/server/src/api/index.js b/packages/server/src/api/index.ts similarity index 70% rename from packages/server/src/api/index.js rename to packages/server/src/api/index.ts index 4cd574f557..a77fc62b9b 100644 --- a/packages/server/src/api/index.js +++ b/packages/server/src/api/index.ts @@ -1,20 +1,15 @@ -const Router = require("@koa/router") -const { - buildAuthMiddleware, - auditLog, - buildTenancyMiddleware, -} = require("@budibase/backend-core/auth") -const { errors } = require("@budibase/backend-core") -const currentApp = require("../middleware/currentapp") +import Router from "@koa/router" +import { errors, auth } from "@budibase/backend-core" +import currentApp from "../middleware/currentapp" +import zlib from "zlib" +import { mainRoutes, staticRoutes, publicRoutes } from "./routes" +import pkg from "../../package.json" +import env from "../environment" +import { middleware as pro } from "@budibase/pro" +export { shutdown } from "./routes/public" const compress = require("koa-compress") -const zlib = require("zlib") -const { mainRoutes, staticRoutes, publicRoutes } = require("./routes") -const pkg = require("../../package.json") -const env = require("../environment") -const { middleware: pro } = require("@budibase/pro") -const { shutdown } = require("./routes/public") -const router = new Router() +export const router: Router = new Router() router.get("/health", ctx => (ctx.status = 200)) router.get("/version", ctx => (ctx.body = pkg.version)) @@ -42,7 +37,7 @@ router // re-direct before any middlewares occur .redirect("/", "/builder") .use( - buildAuthMiddleware(null, { + auth.buildAuthMiddleware(null, { publicAllowed: true, }) ) @@ -50,19 +45,20 @@ router // the server can be public anywhere, so nowhere should throw errors // if the tenancy has not been set, it'll have to be discovered at application layer .use( - buildTenancyMiddleware(null, null, { + auth.buildTenancyMiddleware(null, null, { noTenancyRequired: true, }) ) .use(pro.licensing()) + // @ts-ignore .use(currentApp) - .use(auditLog) + .use(auth.auditLog) // error handling middleware router.use(async (ctx, next) => { try { await next() - } catch (err) { + } catch (err: any) { ctx.status = err.status || err.statusCode || 500 const error = errors.getPublicError(err) ctx.body = { @@ -91,6 +87,3 @@ router.use(publicRoutes.allowedMethods()) // WARNING - static routes will catch everything else after them this must be last router.use(staticRoutes.routes()) router.use(staticRoutes.allowedMethods()) - -module.exports.router = router -module.exports.shutdown = shutdown diff --git a/packages/server/src/api/routes/layout.ts b/packages/server/src/api/routes/layout.ts index 6ec48b9263..cdfdb4002a 100644 --- a/packages/server/src/api/routes/layout.ts +++ b/packages/server/src/api/routes/layout.ts @@ -1,7 +1,7 @@ import Router from "@koa/router" import authorized from "../../middleware/authorized" import { permissions } from "@budibase/backend-core" -import controller from "../controllers/layout" +import * as controller from "../controllers/layout" const router: Router = new Router() diff --git a/packages/server/src/api/routes/script.ts b/packages/server/src/api/routes/script.ts index 44f1069c9e..271cbc51c6 100644 --- a/packages/server/src/api/routes/script.ts +++ b/packages/server/src/api/routes/script.ts @@ -1,7 +1,7 @@ import Router from "@koa/router" import * as controller from "../controllers/script" import authorized from "../../middleware/authorized" -import { permissions } from "@budibase/backend-core/permissions" +import { permissions } from "@budibase/backend-core" const router: Router = new Router() diff --git a/packages/server/src/api/routes/tests/permissions.spec.js b/packages/server/src/api/routes/tests/permissions.spec.js index b416d1c0bf..093f63913a 100644 --- a/packages/server/src/api/routes/tests/permissions.spec.js +++ b/packages/server/src/api/routes/tests/permissions.spec.js @@ -1,6 +1,7 @@ -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") +const { roles } = require("@budibase/backend-core") const setup = require("./utilities") const { basicRow } = setup.structures +const { BUILTIN_ROLE_IDS } = roles const HIGHER_ROLE_ID = BUILTIN_ROLE_IDS.BASIC const STD_ROLE_ID = BUILTIN_ROLE_IDS.PUBLIC diff --git a/packages/server/src/api/routes/tests/role.spec.js b/packages/server/src/api/routes/tests/role.spec.js index 56a3f1e9d9..8402a7b13c 100644 --- a/packages/server/src/api/routes/tests/role.spec.js +++ b/packages/server/src/api/routes/tests/role.spec.js @@ -1,10 +1,8 @@ -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") -const { - BuiltinPermissionID, -} = require("@budibase/backend-core/permissions") +const { roles, events, permissions } = require("@budibase/backend-core") const setup = require("./utilities") const { basicRole } = setup.structures -const { events } = require("@budibase/backend-core") +const { BUILTIN_ROLE_IDS } = roles +const { BuiltinPermissionID } = permissions describe("/roles", () => { let request = setup.getRequest() diff --git a/packages/server/src/api/routes/tests/routing.spec.js b/packages/server/src/api/routes/tests/routing.spec.js index 1c3abf2457..148e5eded1 100644 --- a/packages/server/src/api/routes/tests/routing.spec.js +++ b/packages/server/src/api/routes/tests/routing.spec.js @@ -1,7 +1,8 @@ const setup = require("./utilities") const { basicScreen } = setup.structures const { checkBuilderEndpoint, runInProd } = require("./utilities/TestFunctions") -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") +const { roles } = require("@budibase/backend-core") +const { BUILTIN_ROLE_IDS } = roles const route = "/test" diff --git a/packages/server/src/api/routes/tests/row.spec.js b/packages/server/src/api/routes/tests/row.spec.js index afcc73fd36..65e6df544a 100644 --- a/packages/server/src/api/routes/tests/row.spec.js +++ b/packages/server/src/api/routes/tests/row.spec.js @@ -1,8 +1,7 @@ const { outputProcessing } = require("../../../utilities/rowProcessor") const setup = require("./utilities") const { basicRow } = setup.structures -const { doInAppContext } = require("@budibase/backend-core/context") -const { doInTenant } = require("@budibase/backend-core/tenancy") +const { context, tenancy } = require("@budibase/backend-core") const { quotas, } = require("@budibase/pro") @@ -447,7 +446,7 @@ describe("/rows", () => { describe("fetchEnrichedRows", () => { it("should allow enriching some linked rows", async () => { - const { table, firstRow, secondRow } = await doInTenant( + const { table, firstRow, secondRow } = await tenancy.doInTenant( setup.structures.TENANT_ID, async () => { const table = await config.createLinkedTable() @@ -507,7 +506,7 @@ describe("/rows", () => { }) // the environment needs configured for this await setup.switchToSelfHosted(async () => { - doInAppContext(config.getAppId(), async () => { + context.doInAppContext(config.getAppId(), async () => { const enriched = await outputProcessing(table, [row]) expect(enriched[0].attachment[0].url).toBe( `/prod-budi-app-assets/${config.getAppId()}/attachments/test/thing.csv` diff --git a/packages/server/src/api/routes/tests/user.spec.js b/packages/server/src/api/routes/tests/user.spec.js index 29c33b3899..7e4bf02616 100644 --- a/packages/server/src/api/routes/tests/user.spec.js +++ b/packages/server/src/api/routes/tests/user.spec.js @@ -1,6 +1,7 @@ -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") +const { roles } = require("@budibase/backend-core") const { checkPermissionsEndpoint } = require("./utilities/TestFunctions") const setup = require("./utilities") +const { BUILTIN_ROLE_IDS } = roles jest.mock("../../../utilities/workerRequests", () => ({ getGlobalUsers: jest.fn(() => { diff --git a/packages/server/src/api/routes/tests/utilities/TestFunctions.ts b/packages/server/src/api/routes/tests/utilities/TestFunctions.ts index a34527e8f2..3ac7dea5ac 100644 --- a/packages/server/src/api/routes/tests/utilities/TestFunctions.ts +++ b/packages/server/src/api/routes/tests/utilities/TestFunctions.ts @@ -1,10 +1,8 @@ import * as rowController from "../../../controllers/row" import * as appController from "../../../controllers/application" import { AppStatus } from "../../../../db/utils" -import { BUILTIN_ROLE_IDS } from "@budibase/backend-core/roles" -import { doInTenant } from "@budibase/backend-core/tenancy" +import { roles, tenancy, context } from "@budibase/backend-core" import { TENANT_ID } from "../../../../tests/utilities/structures" -import { getAppDB, doInAppContext } from "@budibase/backend-core/context" import * as env from "../../../../environment" class Request { @@ -21,7 +19,7 @@ class Request { } function runRequest(appId: any, controlFunc: any, request?: any) { - return doInAppContext(appId, async () => { + return context.doInAppContext(appId, async () => { return controlFunc(request) }) } @@ -33,7 +31,7 @@ export const getAllTableRows = async (config: any) => { } export const clearAllApps = async (tenantId = TENANT_ID) => { - await doInTenant(tenantId, async () => { + await tenancy.doInTenant(tenantId, async () => { const req: any = { query: { status: AppStatus.DEV }, user: { tenantId } } await appController.fetch(req) const apps = req.body @@ -51,7 +49,7 @@ export const clearAllApps = async (tenantId = TENANT_ID) => { export const clearAllAutomations = async (config: any) => { const automations = await config.getAllAutomations() for (let auto of automations) { - await doInAppContext(config.appId, async () => { + await context.doInAppContext(config.appId, async () => { await config.deleteAutomation(auto) }) } @@ -110,7 +108,7 @@ export const checkPermissionsEndpoint = async ({ .expect(200) let failHeader - if (failRole === BUILTIN_ROLE_IDS.PUBLIC) { + if (failRole === roles.BUILTIN_ROLE_IDS.PUBLIC) { failHeader = config.publicHeaders({ prodApp: true }) } else { failHeader = await config.login({ @@ -127,7 +125,7 @@ export const checkPermissionsEndpoint = async ({ } export const getDB = () => { - return getAppDB() + return context.getAppDB() } export const testAutomation = async (config: any, automation: any) => { diff --git a/packages/server/src/api/routes/user.ts b/packages/server/src/api/routes/user.ts index 95010bf8f2..60eaf5b1b9 100644 --- a/packages/server/src/api/routes/user.ts +++ b/packages/server/src/api/routes/user.ts @@ -1,5 +1,5 @@ import Router from "@koa/router" -import controller from "../controllers/user" +import * as controller from "../controllers/user" import authorized from "../../middleware/authorized" import { permissions } from "@budibase/backend-core" const { PermissionType, PermissionLevel } = permissions diff --git a/packages/server/src/app.ts b/packages/server/src/app.ts index 9253186498..8a9c1d5b24 100644 --- a/packages/server/src/app.ts +++ b/packages/server/src/app.ts @@ -19,10 +19,9 @@ const http = require("http") const api = require("./api") const automations = require("./automations/index") const Sentry = require("@sentry/node") -const { logAlert } = require("@budibase/backend-core/logging") const { Thread } = require("./threads") -import redis from "./utilities/redis" -import { events } from "@budibase/backend-core" +import * as redis from "./utilities/redis" +import { events, logging } from "@budibase/backend-core" import { initialise as initialiseWebsockets } from "./websocket" import { startup } from "./startup" @@ -93,7 +92,7 @@ process.on("uncaughtException", err => { return } errCode = -1 - logAlert("Uncaught exception.", err) + logging.logAlert("Uncaught exception.", err) shutdown() }) diff --git a/packages/server/src/automations/triggers.js b/packages/server/src/automations/triggers.js index 3481cebf9b..4f865d4df8 100644 --- a/packages/server/src/automations/triggers.js +++ b/packages/server/src/automations/triggers.js @@ -8,8 +8,7 @@ const { automationQueue } = require("./bullboard") const { checkTestFlag } = require("../utilities/redis") const utils = require("./utils") const env = require("../environment") -const { doInAppContext, getAppDB } = require("@budibase/backend-core/context") -const { getAllApps } = require("@budibase/backend-core/db") +const { context, db: dbCore } = require("@budibase/backend-core") const TRIGGER_DEFINITIONS = definitions const JOB_OPTS = { @@ -18,7 +17,7 @@ const JOB_OPTS = { } async function getAllAutomations() { - const db = getAppDB() + const db = context.getAppDB() let automations = await db.allDocs( getAutomationParams(null, { include_docs: true }) ) @@ -30,7 +29,7 @@ async function queueRelevantRowAutomations(event, eventType) { throw `No appId specified for ${eventType} - check event emitters.` } - doInAppContext(event.appId, async () => { + context.doInAppContext(event.appId, async () => { let automations = await getAllAutomations() // filter down to the correct event type @@ -122,9 +121,9 @@ exports.rebootTrigger = async () => { } // iterate through all production apps, find the reboot crons // and trigger events for them - const appIds = await getAllApps({ dev: false, idsOnly: true }) + const appIds = await dbCore.getAllApps({ dev: false, idsOnly: true }) for (let prodAppId of appIds) { - await doInAppContext(prodAppId, async () => { + await context.doInAppContext(prodAppId, async () => { let automations = await getAllAutomations() let rebootEvents = [] for (let automation of automations) { diff --git a/packages/server/src/constants/index.js b/packages/server/src/constants/index.js index 6d8fe57baa..5f68cc26ed 100644 --- a/packages/server/src/constants/index.js +++ b/packages/server/src/constants/index.js @@ -1,6 +1,4 @@ -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") -const { UserStatus } = require("@budibase/backend-core/constants") -const { objectStore } = require("@budibase/backend-core") +const { objectStore, roles, constants } = require("@budibase/backend-core") const FilterTypes = { STRING: "string", @@ -139,7 +137,7 @@ exports.USERS_TABLE_SCHEMA = { constraints: { type: exports.FieldTypes.STRING, presence: false, - inclusion: Object.values(BUILTIN_ROLE_IDS), + inclusion: Object.values(roles.BUILTIN_ROLE_IDS), }, }, status: { @@ -149,7 +147,7 @@ exports.USERS_TABLE_SCHEMA = { constraints: { type: exports.FieldTypes.STRING, presence: false, - inclusion: Object.values(UserStatus), + inclusion: Object.values(constants.UserStatus), }, }, }, diff --git a/packages/server/src/constants/screens.js b/packages/server/src/constants/screens.js index 23f8bc88df..dc21c0d9bd 100644 --- a/packages/server/src/constants/screens.js +++ b/packages/server/src/constants/screens.js @@ -1,4 +1,4 @@ -const { BUILTIN_ROLE_IDS } = require("@budibase/backend-core/roles") +const { roles } = require("@budibase/backend-core") const { BASE_LAYOUT_PROP_IDS } = require("./layouts") exports.createHomeScreen = () => ({ @@ -40,7 +40,7 @@ exports.createHomeScreen = () => ({ }, routing: { route: "/", - roleId: BUILTIN_ROLE_IDS.BASIC, + roleId: roles.BUILTIN_ROLE_IDS.BASIC, }, name: "home-screen", }) diff --git a/packages/server/src/db/inMemoryView.js b/packages/server/src/db/inMemoryView.js index 57ea89071c..278b906e24 100644 --- a/packages/server/src/db/inMemoryView.js +++ b/packages/server/src/db/inMemoryView.js @@ -2,8 +2,8 @@ const newid = require("./newid") // bypass the main application db config // use in memory pouchdb directly -const { getPouch, closePouchDB } = require("@budibase/backend-core/db") -const Pouch = getPouch({ inMemory: true }) +const { db: dbCore } = require("@budibase/backend-core") +const Pouch = dbCore.getPouch({ inMemory: true }) exports.runView = async (view, calculation, group, data) => { // use a different ID each time for the DB, make sure they @@ -44,6 +44,6 @@ exports.runView = async (view, calculation, group, data) => { return response } finally { await db.destroy() - await closePouchDB(db) + await dbCore.closePouchDB(db) } } diff --git a/packages/server/src/db/linkedRows/LinkController.js b/packages/server/src/db/linkedRows/LinkController.js index e7c338f709..df24b97e85 100644 --- a/packages/server/src/db/linkedRows/LinkController.js +++ b/packages/server/src/db/linkedRows/LinkController.js @@ -2,12 +2,12 @@ const { IncludeDocs, getLinkDocuments } = require("./linkUtils") const { InternalTables, getUserMetadataParams } = require("../utils") const Sentry = require("@sentry/node") const { FieldTypes, RelationshipTypes } = require("../../constants") -const { getAppDB } = require("@budibase/backend-core/context") +const { context } = require("@budibase/backend-core") const LinkDocument = require("./LinkDocument") class LinkController { constructor({ tableId, row, table, oldTable }) { - this._db = getAppDB() + this._db = context.getAppDB() this._tableId = tableId this._row = row this._table = table diff --git a/packages/server/src/db/linkedRows/index.js b/packages/server/src/db/linkedRows/index.js index 45bc72156f..1ee98f6148 100644 --- a/packages/server/src/db/linkedRows/index.js +++ b/packages/server/src/db/linkedRows/index.js @@ -14,7 +14,7 @@ const { getMultiIDParams, USER_METDATA_PREFIX } = require("../../db/utils") const { partition } = require("lodash") const { getGlobalUsersFromMetadata } = require("../../utilities/global") const { processFormulas } = require("../../utilities/rowProcessor/utils") -const { getAppDB } = require("@budibase/backend-core/context") +const { context } = require("@budibase/backend-core") /** * This functionality makes sure that when rows with links are created, updated or deleted they are processed @@ -74,7 +74,7 @@ async function getLinksForRows(rows) { async function getFullLinkedDocs(links) { // create DBs - const db = getAppDB() + const db = context.getAppDB() const linkedRowIds = links.map(link => link.id) const uniqueRowIds = [...new Set(linkedRowIds)] let dbRows = (await db.allDocs(getMultiIDParams(uniqueRowIds))).rows.map( diff --git a/packages/server/src/db/linkedRows/linkUtils.js b/packages/server/src/db/linkedRows/linkUtils.js index 5fc393ecf0..25a1b5fcf8 100644 --- a/packages/server/src/db/linkedRows/linkUtils.js +++ b/packages/server/src/db/linkedRows/linkUtils.js @@ -2,7 +2,7 @@ const Sentry = require("@sentry/node") const { ViewName, getQueryIndex } = require("../utils") const { FieldTypes } = require("../../constants") const { createLinkView } = require("../views/staticViews") -const { getAppDB } = require("@budibase/backend-core/context") +const { context } = require("@budibase/backend-core") /** * Only needed so that boolean parameters are being used for includeDocs @@ -30,7 +30,7 @@ exports.createLinkView = createLinkView */ exports.getLinkDocuments = async function (args) { const { tableId, rowId, includeDocs } = args - const db = getAppDB() + const db = context.getAppDB() let params if (rowId != null) { params = { key: [tableId, rowId] } @@ -89,7 +89,7 @@ exports.getLinkedTableIDs = table => { } exports.getLinkedTable = async (id, tables) => { - const db = getAppDB() + const db = context.getAppDB() let linkedTable = tables.find(table => table._id === id) if (linkedTable) { return linkedTable diff --git a/packages/server/src/db/utils.ts b/packages/server/src/db/utils.ts index 13bf6eb3b5..ac5a6162b9 100644 --- a/packages/server/src/db/utils.ts +++ b/packages/server/src/db/utils.ts @@ -128,7 +128,7 @@ export function getLinkParams(otherProps: any = {}) { * Generates a new layout ID. * @returns {string} The new layout ID which the layout doc can be stored under. */ -export function generateLayoutID(id: string) { +export function generateLayoutID(id?: string) { return `${DocumentType.LAYOUT}${SEPARATOR}${id || newid()}` } diff --git a/packages/server/src/db/views/staticViews.js b/packages/server/src/db/views/staticViews.js index d715c02968..10ad8fd410 100644 --- a/packages/server/src/db/views/staticViews.js +++ b/packages/server/src/db/views/staticViews.js @@ -1,4 +1,4 @@ -const { getAppDB } = require("@budibase/backend-core/context") +const { context } = require("@budibase/backend-core") const { DocumentType, SEPARATOR, ViewName, SearchIndexes } = require("../utils") const SCREEN_PREFIX = DocumentType.SCREEN + SEPARATOR @@ -20,7 +20,7 @@ const SCREEN_PREFIX = DocumentType.SCREEN + SEPARATOR * so it may be slow. */ exports.createLinkView = async () => { - const db = getAppDB() + const db = context.getAppDB() const designDoc = await db.get("_design/database") const view = { map: function (doc) { @@ -54,7 +54,7 @@ exports.createLinkView = async () => { } exports.createRoutingView = async () => { - const db = getAppDB() + const db = context.getAppDB() const designDoc = await db.get("_design/database") const view = { // if using variables in a map function need to inject them before use @@ -75,7 +75,7 @@ exports.createRoutingView = async () => { } async function searchIndex(indexName, fnString) { - const db = getAppDB() + const db = context.getAppDB() const designDoc = await db.get("_design/database") designDoc.indexes = { [indexName]: { diff --git a/packages/server/src/integrations/base/sql.ts b/packages/server/src/integrations/base/sql.ts index f18e9d1d98..43ebc8b1dd 100644 --- a/packages/server/src/integrations/base/sql.ts +++ b/packages/server/src/integrations/base/sql.ts @@ -96,7 +96,7 @@ function generateSelectStatement( ): (string | Knex.Raw)[] { const { resource, meta } = json const schema = meta?.table?.schema - return resource.fields.map(field => { + return resource!.fields.map(field => { const fieldNames = field.split(/\./g) const tableName = fieldNames[0] const columnName = fieldNames[1] diff --git a/packages/server/src/integrations/base/sqlTable.ts b/packages/server/src/integrations/base/sqlTable.ts index 02f7ad8718..2ab610fecd 100644 --- a/packages/server/src/integrations/base/sqlTable.ts +++ b/packages/server/src/integrations/base/sqlTable.ts @@ -185,7 +185,7 @@ class SqlTableQueryBuilder { json.table, json.meta.tables, json.meta.table, - json.meta.renamed + json.meta.renamed! ) break case Operation.DELETE_TABLE: diff --git a/packages/server/src/integrations/index.ts b/packages/server/src/integrations/index.ts index c926aeb992..e6f5968e32 100644 --- a/packages/server/src/integrations/index.ts +++ b/packages/server/src/integrations/index.ts @@ -67,50 +67,54 @@ if ( INTEGRATIONS[SourceName.ORACLE] = oracle.integration } -module.exports = { - getDefinitions: async () => { - const pluginSchemas: { [key: string]: Integration } = {} - if (environment.SELF_HOSTED) { - const plugins = await getPlugins(PluginType.DATASOURCE) - // extract the actual schema from each custom - for (let plugin of plugins) { - const sourceId = plugin.name - pluginSchemas[sourceId] = { - ...plugin.schema["schema"], - custom: true, - } - if (plugin.iconUrl) { - pluginSchemas[sourceId].iconUrl = plugin.iconUrl - } +export async function getDefinitions() { + const pluginSchemas: { [key: string]: Integration } = {} + if (environment.SELF_HOSTED) { + const plugins = await getPlugins(PluginType.DATASOURCE) + // extract the actual schema from each custom + for (let plugin of plugins) { + const sourceId = plugin.name + pluginSchemas[sourceId] = { + ...plugin.schema["schema"], + custom: true, + } + if (plugin.iconUrl) { + pluginSchemas[sourceId].iconUrl = plugin.iconUrl } } - return { - ...cloneDeep(DEFINITIONS), - ...pluginSchemas, - } - }, - getIntegration: async (integration: string) => { - if (INTEGRATIONS[integration]) { - return INTEGRATIONS[integration] - } - if (environment.SELF_HOSTED) { - const plugins = await getPlugins(PluginType.DATASOURCE) - for (let plugin of plugins) { - if (plugin.name === integration) { - // need to use commonJS require due to its dynamic runtime nature - const retrieved: any = await getDatasourcePlugin( - plugin.name, - plugin.jsUrl, - plugin.schema?.hash - ) - if (retrieved.integration) { - return retrieved.integration - } else { - return retrieved - } - } - } - } - throw new Error("No datasource implementation found.") - }, + } + return { + ...cloneDeep(DEFINITIONS), + ...pluginSchemas, + } +} + +export async function getIntegration(integration: string) { + if (INTEGRATIONS[integration]) { + return INTEGRATIONS[integration] + } + if (environment.SELF_HOSTED) { + const plugins = await getPlugins(PluginType.DATASOURCE) + for (let plugin of plugins) { + if (plugin.name === integration) { + // need to use commonJS require due to its dynamic runtime nature + const retrieved: any = await getDatasourcePlugin( + plugin.name, + plugin.jsUrl, + plugin.schema?.hash + ) + if (retrieved.integration) { + return retrieved.integration + } else { + return retrieved + } + } + } + } + throw new Error("No datasource implementation found.") +} + +export default { + getDefinitions, + getIntegration, } diff --git a/packages/server/src/migrations/functions/appUrls.ts b/packages/server/src/migrations/functions/appUrls.ts index 1b563bb932..4d5ce6c30c 100644 --- a/packages/server/src/migrations/functions/appUrls.ts +++ b/packages/server/src/migrations/functions/appUrls.ts @@ -1,4 +1,4 @@ -const { DocumentType } = require("@budibase/backend-core/db") +import { db as dbCore } from "@budibase/backend-core" import { getAppUrl } from "../../api/controllers/application" /** @@ -11,7 +11,7 @@ import { getAppUrl } from "../../api/controllers/application" export const run = async (appDb: any) => { let metadata try { - metadata = await appDb.get(DocumentType.APP_METADATA) + metadata = await appDb.get(dbCore.DocumentType.APP_METADATA) } catch (e) { // sometimes the metadata document doesn't exist // exit early instead of failing the migration diff --git a/packages/server/src/migrations/functions/tests/appUrls.spec.js b/packages/server/src/migrations/functions/tests/appUrls.spec.js index 4551bac160..dafe67712f 100644 --- a/packages/server/src/migrations/functions/tests/appUrls.spec.js +++ b/packages/server/src/migrations/functions/tests/appUrls.spec.js @@ -1,4 +1,4 @@ -const { DocumentType, doWithDB } = require("@budibase/backend-core/db") +const { db: dbCore } = require("@budibase/backend-core") const TestConfig = require("../../../tests/utilities/TestConfiguration") const migration = require("../appUrls") @@ -14,12 +14,12 @@ describe("run", () => { it("runs successfully", async () => { const app = await config.createApp("testApp") - const metadata = await doWithDB(app.appId, async db => { - const metadataDoc = await db.get( DocumentType.APP_METADATA) + const metadata = await dbCore.doWithDB(app.appId, async db => { + const metadataDoc = await db.get(dbCore.DocumentType.APP_METADATA) delete metadataDoc.url await db.put(metadataDoc) await migration.run(db) - return await db.get( DocumentType.APP_METADATA) + return await db.get(dbCore.DocumentType.APP_METADATA) }) expect(metadata.url).toEqual("/testapp") }) diff --git a/packages/server/src/migrations/functions/tests/userEmailViewCasing.spec.js b/packages/server/src/migrations/functions/tests/userEmailViewCasing.spec.js index 3c8894f8e5..e6e6725f07 100644 --- a/packages/server/src/migrations/functions/tests/userEmailViewCasing.spec.js +++ b/packages/server/src/migrations/functions/tests/userEmailViewCasing.spec.js @@ -1,11 +1,16 @@ -jest.mock("@budibase/backend-core/db", () => ({ - ...jest.requireActual("@budibase/backend-core/db"), - createNewUserEmailView: jest.fn(), -})) -const coreDb = require("@budibase/backend-core/db") +jest.mock("@budibase/backend-core", () => { + const core = jest.requireActual("@budibase/backend-core") + return { + ...core, + db: { + ...core.db, + createNewUserEmailView: jest.fn() + } + } +}) +const { tenancy, db: dbCore } = require("@budibase/backend-core") const TestConfig = require("../../../tests/utilities/TestConfiguration") const { TENANT_ID } = require("../../../tests/utilities/structures") -const { getGlobalDB, doInTenant } = require("@budibase/backend-core/tenancy") // mock email view creation @@ -21,10 +26,10 @@ describe("run", () => { afterAll(config.end) it("runs successfully", async () => { - await doInTenant(TENANT_ID, async () => { - const globalDb = getGlobalDB() + await tenancy.doInTenant(TENANT_ID, async () => { + const globalDb = tenancy.getGlobalDB() await migration.run(globalDb) - expect(coreDb.createNewUserEmailView).toHaveBeenCalledTimes(1) + expect(dbCore.createNewUserEmailView).toHaveBeenCalledTimes(1) }) }) }) diff --git a/packages/server/src/migrations/functions/usageQuotas/syncApps.ts b/packages/server/src/migrations/functions/usageQuotas/syncApps.ts index 76e2dbdacd..351154dccc 100644 --- a/packages/server/src/migrations/functions/usageQuotas/syncApps.ts +++ b/packages/server/src/migrations/functions/usageQuotas/syncApps.ts @@ -1,15 +1,14 @@ -import { getTenantId } from "@budibase/backend-core/tenancy" -import { getAllApps } from "@budibase/backend-core/db" +import { tenancy, db as dbCore } from "@budibase/backend-core" import { quotas } from "@budibase/pro" import { QuotaUsageType, StaticQuotaName } from "@budibase/types" export const run = async () => { // get app count - const devApps = await getAllApps({ dev: true }) + const devApps = await dbCore.getAllApps({ dev: true }) const appCount = devApps ? devApps.length : 0 // sync app count - const tenantId = getTenantId() + const tenantId = tenancy.getTenantId() console.log(`[Tenant: ${tenantId}] Syncing app count: ${appCount}`) await quotas.setUsage(appCount, StaticQuotaName.APPS, QuotaUsageType.STATIC) } diff --git a/packages/server/src/migrations/functions/usageQuotas/syncRows.ts b/packages/server/src/migrations/functions/usageQuotas/syncRows.ts index e5c8a1743c..92574d1f27 100644 --- a/packages/server/src/migrations/functions/usageQuotas/syncRows.ts +++ b/packages/server/src/migrations/functions/usageQuotas/syncRows.ts @@ -1,12 +1,11 @@ -import { getTenantId } from "@budibase/backend-core/tenancy" -import { getAllApps } from "@budibase/backend-core/db" +import { tenancy, db as dbCore } from "@budibase/backend-core" import { getUniqueRows } from "../../../utilities/usageQuota/rows" import { quotas } from "@budibase/pro" import { StaticQuotaName, QuotaUsageType, App } from "@budibase/types" export const run = async () => { // get all rows in all apps - const allApps = (await getAllApps({ all: true })) as App[] + const allApps = (await dbCore.getAllApps({ all: true })) as App[] const appIds = allApps ? allApps.map((app: { appId: any }) => app.appId) : [] const { appRows } = await getUniqueRows(appIds) @@ -19,7 +18,7 @@ export const run = async () => { }) // sync row count - const tenantId = getTenantId() + const tenantId = tenancy.getTenantId() console.log(`[Tenant: ${tenantId}] Syncing row count: ${rowCount}`) await quotas.setUsagePerApp( counts, diff --git a/packages/server/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts b/packages/server/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts index b0d429fbe8..a5cb203e0f 100644 --- a/packages/server/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts +++ b/packages/server/src/migrations/functions/usageQuotas/tests/syncRows.spec.ts @@ -2,7 +2,7 @@ import TestConfig from "../../../../tests/utilities/TestConfiguration" import * as syncRows from "../syncRows" import { quotas } from "@budibase/pro" import { QuotaUsageType, StaticQuotaName } from "@budibase/types" -const { getProdAppID } = require("@budibase/backend-core/db") +const { db: dbCore } = require("@budibase/backend-core") describe("syncRows", () => { let config = new TestConfig(false) @@ -38,12 +38,12 @@ describe("syncRows", () => { // assert the migration worked usageDoc = await quotas.getQuotaUsage() expect(usageDoc.usageQuota.rows).toEqual(3) - expect(usageDoc.apps?.[getProdAppID(app1.appId)].usageQuota.rows).toEqual( - 1 - ) - expect(usageDoc.apps?.[getProdAppID(app2.appId)].usageQuota.rows).toEqual( - 2 - ) + expect( + usageDoc.apps?.[dbCore.getProdAppID(app1.appId)].usageQuota.rows + ).toEqual(1) + expect( + usageDoc.apps?.[dbCore.getProdAppID(app2.appId)].usageQuota.rows + ).toEqual(2) }) }) }) diff --git a/packages/server/src/migrations/functions/userEmailViewCasing.ts b/packages/server/src/migrations/functions/userEmailViewCasing.ts index fe58692a27..078289cddf 100644 --- a/packages/server/src/migrations/functions/userEmailViewCasing.ts +++ b/packages/server/src/migrations/functions/userEmailViewCasing.ts @@ -1,4 +1,4 @@ -const { createNewUserEmailView } = require("@budibase/backend-core/db") +import { db as dbCore } from "@budibase/backend-core" /** * Date: @@ -8,6 +8,6 @@ const { createNewUserEmailView } = require("@budibase/backend-core/db") * Recreate the user email view to include latest changes i.e. lower casing the email address */ -export const run = async (db: any) => { - await createNewUserEmailView(db) +export const run = async () => { + await dbCore.createNewUserEmailView() } diff --git a/packages/server/src/module.d.ts b/packages/server/src/module.d.ts deleted file mode 100644 index ada45a3a66..0000000000 --- a/packages/server/src/module.d.ts +++ /dev/null @@ -1,14 +0,0 @@ -declare module "@budibase/backend-core/tenancy" -declare module "@budibase/backend-core/db" -declare module "@budibase/backend-core/context" -declare module "@budibase/backend-core/cache" -declare module "@budibase/backend-core/permissions" -declare module "@budibase/backend-core/roles" -declare module "@budibase/backend-core/constants" -declare module "@budibase/backend-core/auth" -declare module "@budibase/backend-core/sessions" -declare module "@budibase/backend-core/encryption" -declare module "@budibase/backend-core/utils" -declare module "@budibase/backend-core/redis" -declare module "@budibase/backend-core/objectStore" -declare module "@budibase/backend-core/plugins" diff --git a/packages/server/src/startup.ts b/packages/server/src/startup.ts index 7d3302655a..53fcf3ebef 100644 --- a/packages/server/src/startup.ts +++ b/packages/server/src/startup.ts @@ -1,5 +1,5 @@ import * as env from "./environment" -import redis from "./utilities/redis" +import * as redis from "./utilities/redis" import { createAdminUser, generateApiKey, @@ -19,7 +19,7 @@ import eventEmitter from "./events" import * as migrations from "./migrations" import bullboard from "./automations/bullboard" import * as pro from "@budibase/pro" -import api from "./api" +import * as api from "./api" import sdk from "./sdk" const pino = require("koa-pino-logger") diff --git a/packages/server/src/threads/automation.ts b/packages/server/src/threads/automation.ts index 3552ffa0f3..5e2817ed06 100644 --- a/packages/server/src/threads/automation.ts +++ b/packages/server/src/threads/automation.ts @@ -23,15 +23,14 @@ import { AutomationMetadata, } from "../definitions/automations" import { WorkerCallback } from "./definitions" -const { doInAppContext, getAppDB } = require("@budibase/backend-core/context") -const { logAlertWithInfo, logWarn } = require("@budibase/backend-core/logging") -const { processObject } = require("@budibase/string-templates") +import { context, logging } from "@budibase/backend-core" +import { processObject } from "@budibase/string-templates" +import { cloneDeep } from "lodash/fp" +import env from "../environment" const FILTER_STEP_ID = actions.ACTION_DEFINITIONS.FILTER.stepId const LOOP_STEP_ID = actions.ACTION_DEFINITIONS.LOOP.stepId const CRON_STEP_ID = triggerDefs.CRON.stepId const STOPPED_STATUS = { success: true, status: AutomationStatus.STOPPED } -const { cloneDeep } = require("lodash/fp") -const env = require("../environment") function typecastForLooping(loopStep: LoopStep, input: LoopInput) { if (!input || !input.binding) { @@ -121,7 +120,7 @@ class Orchestrator { async getMetadata(): Promise { const metadataId = generateAutomationMetadataID(this._automation._id!) - const db = getAppDB() + const db = context.getAppDB() let metadata: AutomationMetadata try { metadata = await db.get(metadataId) @@ -138,7 +137,7 @@ class Orchestrator { if (!this._job.opts.repeat) { return } - logWarn( + logging.logWarn( `CRON disabled reason=${reason} - ${this._appId}/${this._automation._id}` ) const automation = this._automation @@ -184,14 +183,14 @@ class Orchestrator { } else { metadata.errorCount = 0 } - const db = getAppDB() + const db = context.getAppDB() try { await db.put(metadata) } catch (err) { - logAlertWithInfo( + logging.logAlertWithInfo( "Failed to write automation metadata", db.name, - automation._id, + automation._id!, err ) } @@ -265,7 +264,7 @@ class Orchestrator { for (let step of automation.definition.steps) { stepCount++ - let input, + let input: any, iterations = 1, iterationCount = 0 @@ -283,7 +282,7 @@ class Orchestrator { let originalStepInput = cloneDeep(step.inputs) // Handle if the user has set a max iteration count or if it reaches the max limit set by us if (loopStep && input.binding) { - let newInput = await processObject( + let newInput: any = await processObject( loopStep.inputs, cloneDeep(this._context) ) @@ -352,7 +351,7 @@ class Orchestrator { } } if ( - index === env.AUTOMATION_MAX_ITERATION || + index === env.AUTOMATION_MAX_ITERATIONS || index === parseInt(loopStep.inputs.iterations) ) { this.updateContextAndOutput(loopStepNumber, step, tempOutput, { @@ -481,7 +480,7 @@ export function execute(job: Job, callback: WorkerCallback) { if (!appId) { throw new Error("Unable to execute, event doesn't contain app ID.") } - doInAppContext(appId, async () => { + return context.doInAppContext(appId, async () => { const automationOrchestrator = new Orchestrator(job) try { const response = await automationOrchestrator.execute() @@ -497,7 +496,7 @@ export const removeStalled = async (job: Job) => { if (!appId) { throw new Error("Unable to execute, event doesn't contain app ID.") } - await doInAppContext(appId, async () => { + await context.doInAppContext(appId, async () => { const automationOrchestrator = new Orchestrator(job) await automationOrchestrator.stopCron("stalled") }) diff --git a/packages/server/src/threads/query.ts b/packages/server/src/threads/query.ts index 86cbf89c87..8ee8bcb463 100644 --- a/packages/server/src/threads/query.ts +++ b/packages/server/src/threads/query.ts @@ -1,17 +1,12 @@ import { default as threadUtils } from "./utils" threadUtils.threadSetup() import { WorkerCallback, QueryEvent, QueryVariable } from "./definitions" -const ScriptRunner = require("../utilities/scriptRunner") -const { getIntegration } = require("../integrations") -const { processStringSync } = require("@budibase/string-templates") -const { doInAppContext, getAppDB } = require("@budibase/backend-core/context") -const { - refreshOAuthToken, - updateUserOAuth, -} = require("@budibase/backend-core/auth") -const { user: userCache } = require("@budibase/backend-core/cache") -const { getGlobalIDFromUserMetadataID } = require("../db/utils") -const { cloneDeep } = require("lodash/fp") +import ScriptRunner from "../utilities/scriptRunner" +import { getIntegration } from "../integrations" +import { processStringSync } from "@budibase/string-templates" +import { context, cache, auth } from "@budibase/backend-core" +import { getGlobalIDFromUserMetadataID } from "../db/utils" +import { cloneDeep } from "lodash/fp" const { isSQL } = require("../integrations/utils") const { @@ -170,7 +165,7 @@ class QueryRunner { } async runAnotherQuery(queryId: string, parameters: any) { - const db = getAppDB() + const db = context.getAppDB() const query = await db.get(queryId) const datasource = await db.get(query.datasourceId) return new QueryRunner( @@ -194,7 +189,7 @@ class QueryRunner { throw new Error("No refresh token found for authenticated user") } - const resp = await refreshOAuthToken( + const resp: any = await auth.refreshOAuthToken( oauth2.refreshToken, providerType, configId @@ -204,8 +199,8 @@ class QueryRunner { // There are several other properties available in 'resp' if (!resp.err) { const globalUserId = getGlobalIDFromUserMetadataID(_id) - await updateUserOAuth(globalUserId, resp) - this.ctx.user = await userCache.getUser(globalUserId) + await auth.updateUserOAuth(globalUserId, resp) + this.ctx.user = await cache.user.getUser(globalUserId) } else { // In this event the user may have oAuth issues that // could require re-authenticating with their provider. @@ -285,7 +280,7 @@ class QueryRunner { } export function execute(input: QueryEvent, callback: WorkerCallback) { - doInAppContext(input.appId, async () => { + context.doInAppContext(input.appId!, async () => { const Runner = new QueryRunner(input) try { const response = await Runner.execute() diff --git a/packages/server/src/threads/utils.ts b/packages/server/src/threads/utils.ts index a51c861b00..53120160a8 100644 --- a/packages/server/src/threads/utils.ts +++ b/packages/server/src/threads/utils.ts @@ -1,8 +1,7 @@ import { QueryVariable } from "./definitions" -const env = require("../environment") -const db = require("../db") -const redis = require("@budibase/backend-core/redis") -const { SEPARATOR } = require("@budibase/backend-core/db") +import env from "../environment" +import db from "../db" +import { redis, db as dbCore } from "@budibase/backend-core" const VARIABLE_TTL_SECONDS = 3600 let client: any @@ -21,7 +20,7 @@ process.on("exit", async () => { }) function makeVariableKey(queryId: string, variable: string) { - return `${queryId}${SEPARATOR}${variable}` + return `${queryId}${dbCore.SEPARATOR}${variable}` } export function threadSetup() { diff --git a/packages/server/src/utilities/redis.ts b/packages/server/src/utilities/redis.ts index 8659843dbb..1b7a3ce64c 100644 --- a/packages/server/src/utilities/redis.ts +++ b/packages/server/src/utilities/redis.ts @@ -1,6 +1,6 @@ import { redis } from "@budibase/backend-core" import { getGlobalIDFromUserMetadataID } from "../db/utils" -import { User } from "@budibase/types" +import { ContextUser } from "@budibase/types" const APP_DEV_LOCK_SECONDS = 600 const AUTOMATION_TEST_FLAG_SECONDS = 60 @@ -24,7 +24,7 @@ export async function shutdown() { console.log("Redis shutdown") } -export async function doesUserHaveLock(devAppId: string, user: User) { +export async function doesUserHaveLock(devAppId: string, user: ContextUser) { const value = await devAppClient.get(devAppId) if (!value) { return true @@ -39,7 +39,7 @@ export async function getLocksById(appIds: string[]) { return await devAppClient.bulkGet(appIds) } -export async function updateLock(devAppId: string, user: User) { +export async function updateLock(devAppId: string, user: ContextUser) { // make sure always global user ID const globalId = getGlobalIDFromUserMetadataID(user._id!) const inputUser = { @@ -52,7 +52,7 @@ export async function updateLock(devAppId: string, user: User) { await devAppClient.store(devAppId, inputUser, APP_DEV_LOCK_SECONDS) } -export async function clearLock(devAppId: string, user: User) { +export async function clearLock(devAppId: string, user: ContextUser) { const value = await devAppClient.get(devAppId) if (!value) { return diff --git a/packages/server/src/utilities/rowProcessor/index.ts b/packages/server/src/utilities/rowProcessor/index.ts index 2b4f4e05a6..5595d0c5fb 100644 --- a/packages/server/src/utilities/rowProcessor/index.ts +++ b/packages/server/src/utilities/rowProcessor/index.ts @@ -180,7 +180,7 @@ export function inputProcessing( */ export async function outputProcessing( table: Table, - rows: Row[], + rows: Row[] | Row, opts = { squash: true } ) { let wasArray = true diff --git a/packages/server/src/watch.ts b/packages/server/src/watch.ts index 4beef5ddb8..2ef132c19d 100644 --- a/packages/server/src/watch.ts +++ b/packages/server/src/watch.ts @@ -2,8 +2,7 @@ import path from "path" import * as env from "./environment" import chokidar from "chokidar" import fs from "fs" -import { tenancy } from "@budibase/backend-core" -import { DEFAULT_TENANT_ID } from "@budibase/backend-core/constants" +import { constants, tenancy } from "@budibase/backend-core" import { processUploadedPlugin } from "./api/controllers/plugin" export function watch() { @@ -23,7 +22,7 @@ export function watch() { if (!path?.endsWith(".tar.gz") || !fs.existsSync(path)) { return } - await tenancy.doInTenant(DEFAULT_TENANT_ID, async () => { + await tenancy.doInTenant(constants.DEFAULT_TENANT_ID, async () => { try { const split = path.split("/") const name = split[split.length - 1] diff --git a/packages/types/src/sdk/events/role.ts b/packages/types/src/sdk/events/role.ts index adeb169a53..b04b9b8ee5 100644 --- a/packages/types/src/sdk/events/role.ts +++ b/packages/types/src/sdk/events/role.ts @@ -3,19 +3,19 @@ import { BaseEvent } from "./event" export interface RoleCreatedEvent extends BaseEvent { roleId: string permissionId: string - inherits: string + inherits?: string } export interface RoleUpdatedEvent extends BaseEvent { roleId: string permissionId: string - inherits: string + inherits?: string } export interface RoleDeletedEvent extends BaseEvent { roleId: string permissionId: string - inherits: string + inherits?: string } export interface RoleAssignedEvent extends BaseEvent {