Typescript conversions - trying to get all of context/db layer into TS.

This commit is contained in:
mike12345567 2022-11-11 11:57:50 +00:00
parent c63c3b48c5
commit bc94f20794
9 changed files with 85 additions and 89 deletions

View File

@ -1,10 +1,10 @@
const cls = require("../clshooked")
const { newid } = require("../hashing")
import cls from "../clshooked"
import { newid } from "../hashing"
const REQUEST_ID_KEY = "requestId"
const MAIN_CTX = cls.createNamespace("main")
function getContextStorage(namespace) {
function getContextStorage(namespace: any) {
if (namespace && namespace.active) {
let contextData = namespace.active
delete contextData.id
@ -15,7 +15,7 @@ function getContextStorage(namespace) {
}
class FunctionContext {
static run(callback) {
static run(callback: any) {
return MAIN_CTX.runAndReturn(async () => {
const namespaceId = newid()
MAIN_CTX.set(REQUEST_ID_KEY, namespaceId)
@ -26,13 +26,13 @@ class FunctionContext {
})
}
static setOnContext(key, value) {
static setOnContext(key: string, value: any) {
const namespaceId = MAIN_CTX.get(REQUEST_ID_KEY)
const namespace = cls.getNamespace(namespaceId)
namespace.set(key, value)
}
static getFromContext(key) {
static getFromContext(key: string) {
const namespaceId = MAIN_CTX.get(REQUEST_ID_KEY)
const namespace = cls.getNamespace(namespaceId)
const context = getContextStorage(namespace)
@ -44,4 +44,4 @@ class FunctionContext {
}
}
module.exports = FunctionContext
export = FunctionContext

View File

@ -1,16 +1,20 @@
const { getGlobalUserParams, getAllApps } = require("../db/utils")
const { doWithDB } = require("../db")
const { doWithGlobalDB } = require("../tenancy")
const { StaticDatabases } = require("../db/constants")
import { getGlobalUserParams, getAllApps } from "../db/utils"
import { doWithDB } from "../db"
import { doWithGlobalDB } from "../tenancy"
import { StaticDatabases } from "../db/constants"
import { PouchLike } from "../couch"
import { User } from "@budibase/types"
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
const removeTenantFromInfoDB = async tenantId => {
async function removeTenantFromInfoDB(tenantId: string) {
try {
await doWithDB(PLATFORM_INFO_DB, async infoDb => {
await doWithDB(PLATFORM_INFO_DB, async (infoDb: PouchLike) => {
let tenants = await infoDb.get(TENANT_DOC)
tenants.tenantIds = tenants.tenantIds.filter(id => id !== tenantId)
tenants.tenantIds = tenants.tenantIds.filter(
(id: string) => id !== tenantId
)
await infoDb.put(tenants)
})
@ -20,32 +24,15 @@ const removeTenantFromInfoDB = async tenantId => {
}
}
exports.removeUserFromInfoDB = async dbUser => {
await doWithDB(PLATFORM_INFO_DB, async infoDb => {
const keys = [dbUser._id, dbUser.email]
const userDocs = await infoDb.allDocs({
keys,
include_docs: true,
})
const toDelete = userDocs.rows.map(row => {
return {
...row.doc,
_deleted: true,
}
})
await infoDb.bulkDocs(toDelete)
})
}
const removeUsersFromInfoDB = async tenantId => {
return doWithGlobalDB(tenantId, async db => {
async function removeUsersFromInfoDB(tenantId: string) {
return doWithGlobalDB(tenantId, async (db: PouchLike) => {
try {
const allUsers = await db.allDocs(
getGlobalUserParams(null, {
include_docs: true,
})
)
await doWithDB(PLATFORM_INFO_DB, async infoDb => {
await doWithDB(PLATFORM_INFO_DB, async (infoDb: PouchLike) => {
const allEmails = allUsers.rows.map(row => row.doc.email)
// get the id docs
let keys = allUsers.rows.map(row => row.id)
@ -71,8 +58,8 @@ const removeUsersFromInfoDB = async tenantId => {
})
}
const removeGlobalDB = async tenantId => {
return doWithGlobalDB(tenantId, async db => {
async function removeGlobalDB(tenantId: string) {
return doWithGlobalDB(tenantId, async (db: PouchLike) => {
try {
await db.destroy()
} catch (err) {
@ -82,11 +69,11 @@ const removeGlobalDB = async tenantId => {
})
}
const removeTenantApps = async tenantId => {
async function removeTenantApps(tenantId: string) {
try {
const apps = await getAllApps({ all: true })
const destroyPromises = apps.map(app =>
doWithDB(app.appId, db => db.destroy())
doWithDB(app.appId, (db: PouchLike) => db.destroy())
)
await Promise.allSettled(destroyPromises)
} catch (err) {
@ -95,8 +82,25 @@ const removeTenantApps = async tenantId => {
}
}
export async function removeUserFromInfoDB(dbUser: User) {
await doWithDB(PLATFORM_INFO_DB, async (infoDb: PouchLike) => {
const keys = [dbUser._id!, dbUser.email]
const userDocs = await infoDb.allDocs({
keys,
include_docs: true,
})
const toDelete = userDocs.rows.map(row => {
return {
...row.doc,
_deleted: true,
}
})
await infoDb.bulkDocs(toDelete)
})
}
// can't live in tenancy package due to circular dependency on db/utils
exports.deleteTenant = async tenantId => {
export async function deleteTenant(tenantId: string) {
await removeTenantFromInfoDB(tenantId)
await removeUsersFromInfoDB(tenantId)
await removeGlobalDB(tenantId)

View File

@ -203,6 +203,9 @@ export function getAppDB(opts?: any): PouchLike {
*/
export function getProdAppDB(opts?: any): PouchLike {
const appId = getAppId()
if (!appId) {
throw new Error("Unable to retrieve prod DB - no app ID.")
}
return new PouchLike(getProdAppID(appId), opts)
}
@ -212,5 +215,8 @@ export function getProdAppDB(opts?: any): PouchLike {
*/
export function getDevAppDB(opts?: any): PouchLike {
const appId = getAppId()
if (!appId) {
throw new Error("Unable to retrieve dev DB - no app ID.")
}
return new PouchLike(getDevelopmentAppID(appId), opts)
}

View File

@ -1,32 +1,33 @@
import { APP_DEV_PREFIX, APP_PREFIX } from "./constants"
import { App } from "@budibase/types"
const NO_APP_ERROR = "No app provided"
const { APP_DEV_PREFIX, APP_PREFIX } = require("./constants")
exports.isDevAppID = appId => {
export function isDevAppID(appId?: string) {
if (!appId) {
throw NO_APP_ERROR
}
return appId.startsWith(APP_DEV_PREFIX)
}
exports.isProdAppID = appId => {
export function isProdAppID(appId?: string) {
if (!appId) {
throw NO_APP_ERROR
}
return appId.startsWith(APP_PREFIX) && !exports.isDevAppID(appId)
return appId.startsWith(APP_PREFIX) && !isDevAppID(appId)
}
exports.isDevApp = app => {
export function isDevApp(app: App) {
if (!app) {
throw NO_APP_ERROR
}
return exports.isDevAppID(app.appId)
return isDevAppID(app.appId)
}
/**
* Generates a development app ID from a real app ID.
* @returns {string} the dev app ID which can be used for dev database.
*/
exports.getDevelopmentAppID = appId => {
export function getDevelopmentAppID(appId: string) {
if (!appId || appId.startsWith(APP_DEV_PREFIX)) {
return appId
}
@ -36,12 +37,12 @@ exports.getDevelopmentAppID = appId => {
const rest = split.join(APP_PREFIX)
return `${APP_DEV_PREFIX}${rest}`
}
exports.getDevAppID = exports.getDevelopmentAppID
export const getDevAppID = getDevelopmentAppID
/**
* Convert a development app ID to a deployed app ID.
*/
exports.getProdAppID = appId => {
export function getProdAppID(appId: string) {
if (!appId || !appId.startsWith(APP_DEV_PREFIX)) {
return appId
}
@ -52,7 +53,7 @@ exports.getProdAppID = appId => {
return `${APP_PREFIX}${rest}`
}
exports.extractAppUUID = id => {
export function extractAppUUID(id: string) {
const split = id?.split("_") || []
return split.length ? split[split.length - 1] : null
}

View File

@ -11,7 +11,7 @@ import env from "./environment"
import tenancy from "./tenancy"
import featureFlags from "./featureFlags"
import * as sessions from "./security/sessions"
import deprovisioning from "./context/deprovision"
import * as deprovisioning from "./context/deprovision"
import auth from "./auth"
import constants from "./constants"
import * as dbConstants from "./db/constants"

View File

@ -68,7 +68,7 @@ export const getGlobalUserByAppPage = (appId: string, user: User) => {
if (!user) {
return
}
return generateAppUserID(getProdAppID(appId), user._id!)
return generateAppUserID(getProdAppID(appId)!, user._id!)
}
/**

View File

@ -1,23 +1,11 @@
import Deployment from "./Deployment"
import {
getDevelopmentAppID,
getProdAppID,
Replication,
} from "@budibase/backend-core/db"
import { context, db as dbCore, events, cache } from "@budibase/backend-core"
import { DocumentType, getAutomationParams } from "../../../db/utils"
import {
clearMetadata,
disableAllCrons,
enableCronTrigger,
} from "../../../automations/utils"
import { app as appCache } from "@budibase/backend-core/cache"
import {
getAppDB,
getAppId,
getDevAppDB,
getProdAppDB,
} from "@budibase/backend-core/context"
import { events } from "@budibase/backend-core"
import { backups } from "@budibase/pro"
import { AppBackupTrigger } from "@budibase/types"
@ -49,7 +37,7 @@ async function checkAllDeployments(deployments: any) {
async function storeDeploymentHistory(deployment: any) {
const deploymentJSON = deployment.getJSON()
const db = getAppDB()
const db = context.getAppDB()
let deploymentDoc
try {
@ -77,7 +65,7 @@ async function storeDeploymentHistory(deployment: any) {
}
async function initDeployedApp(prodAppId: any) {
const db = getProdAppDB()
const db = context.getProdAppDB()
console.log("Reading automation docs")
const automations = (
await db.allDocs(
@ -103,9 +91,9 @@ async function initDeployedApp(prodAppId: any) {
async function deployApp(deployment: any, userId: string) {
let replication
try {
const appId = getAppId()
const devAppId = getDevelopmentAppID(appId)
const productionAppId = getProdAppID(appId)
const appId = context.getAppId()!
const devAppId = dbCore.getDevelopmentAppID(appId)
const productionAppId = dbCore.getProdAppID(appId)
// don't try this if feature isn't allowed, will error
if (await backups.isEnabled()) {
@ -122,8 +110,8 @@ async function deployApp(deployment: any, userId: string) {
source: devAppId,
target: productionAppId,
}
replication = new Replication(config)
const devDb = getDevAppDB()
replication = new dbCore.Replication(config)
const devDb = context.getDevAppDB()
console.log("Compacting development DB")
await devDb.compact()
console.log("Replication object created")
@ -131,7 +119,7 @@ async function deployApp(deployment: any, userId: string) {
console.log("replication complete.. replacing app meta doc")
// app metadata is excluded as it is likely to be in conflict
// replicate the app metadata document manually
const db = getProdAppDB()
const db = context.getProdAppDB()
const appDoc = await devDb.get(DocumentType.APP_METADATA)
try {
const prodAppDoc = await db.get(DocumentType.APP_METADATA)
@ -147,7 +135,7 @@ async function deployApp(deployment: any, userId: string) {
// remove automation errors if they exist
delete appDoc.automationErrors
await db.put(appDoc)
await appCache.invalidateAppMetadata(productionAppId)
await cache.app.invalidateAppMetadata(productionAppId)
console.log("New app doc written successfully.")
await initDeployedApp(productionAppId)
console.log("Deployed app initialised, setting deployment to successful")
@ -170,7 +158,7 @@ async function deployApp(deployment: any, userId: string) {
export async function fetchDeployments(ctx: any) {
try {
const db = getAppDB()
const db = context.getAppDB()
const deploymentDoc = await db.get(DocumentType.DEPLOYMENTS)
const { updated, deployments } = await checkAllDeployments(deploymentDoc)
if (updated) {
@ -184,7 +172,7 @@ export async function fetchDeployments(ctx: any) {
export async function deploymentProgress(ctx: any) {
try {
const db = getAppDB()
const db = context.getAppDB()
const deploymentDoc = await db.get(DocumentType.DEPLOYMENTS)
ctx.body = deploymentDoc[ctx.params.deploymentId]
} catch (err) {
@ -197,7 +185,7 @@ export async function deploymentProgress(ctx: any) {
const isFirstDeploy = async () => {
try {
const db = getProdAppDB()
const db = context.getProdAppDB()
await db.get(DocumentType.APP_METADATA)
} catch (e: any) {
if (e.status === 404) {

View File

@ -4,15 +4,9 @@ import { automationQueue } from "./bullboard"
import newid from "../db/newid"
import { updateEntityMetadata } from "../utilities"
import { MetadataTypes } from "../constants"
import { getProdAppID, doWithDB } from "@budibase/backend-core/db"
import { db as dbCore, context } from "@budibase/backend-core"
import { getAutomationMetadataParams } from "../db/utils"
import { cloneDeep } from "lodash/fp"
import {
getAppDB,
getAppId,
getProdAppDB,
} from "@budibase/backend-core/context"
import { context } from "@budibase/backend-core"
import { quotas } from "@budibase/pro"
import { Automation, WebhookActionType } from "@budibase/types"
import sdk from "../sdk"
@ -102,7 +96,7 @@ export async function disableCronById(jobId: number | string) {
}
export async function clearMetadata() {
const db = getProdAppDB()
const db = context.getProdAppDB()
const automationMetadata = (
await db.allDocs(
getAutomationMetadataParams({
@ -157,7 +151,7 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
// can't use getAppDB here as this is likely to be called from dev app,
// but this call could be for dev app or prod app, need to just use what
// was passed in
await doWithDB(appId, async (db: any) => {
await dbCore.doWithDB(appId, async (db: any) => {
const response = await db.put(automation)
automation._id = response.id
automation._rev = response.rev
@ -175,7 +169,10 @@ export async function enableCronTrigger(appId: any, automation: Automation) {
* written to DB (this does not write to DB as it would be wasteful to repeat).
*/
export async function checkForWebhooks({ oldAuto, newAuto }: any) {
const appId = getAppId()
const appId = context.getAppId()
if (!appId) {
throw new Error("Unable to check webhooks - no app ID in context.")
}
const oldTrigger = oldAuto ? oldAuto.definition.trigger : null
const newTrigger = newAuto ? newAuto.definition.trigger : null
const triggerChanged =
@ -194,7 +191,7 @@ export async function checkForWebhooks({ oldAuto, newAuto }: any) {
oldTrigger.webhookId
) {
try {
let db = getAppDB()
let db = context.getAppDB()
// need to get the webhook to get the rev
const webhook = await db.get(oldTrigger.webhookId)
// might be updating - reset the inputs to remove the URLs
@ -224,7 +221,7 @@ export async function checkForWebhooks({ oldAuto, newAuto }: any) {
// the app ID has to be development for this endpoint
// it can only be used when building the app
// but the trigger endpoint will always be used in production
const prodAppId = getProdAppID(appId)
const prodAppId = dbCore.getProdAppID(appId)
newTrigger.inputs = {
schemaUrl: `api/webhooks/schema/${appId}/${id}`,
triggerUrl: `api/webhooks/trigger/${prodAppId}/${id}`,

View File

@ -8,7 +8,7 @@ export interface RowResponse<T> {
key: string
error: string
value: RowValue
doc?: T
doc?: T | any
}
export interface AllDocsResponse<T> {