Updating PouchLike to be an interface in types, with its impl stored in backend-core, now called Database.

This commit is contained in:
mike12345567 2022-11-17 14:35:03 +00:00
parent 4c44b7a224
commit c4f041e511
18 changed files with 336 additions and 103 deletions

View File

@ -1,7 +1,7 @@
import BaseCache from "./base" import BaseCache from "./base"
import { getWritethroughClient } from "../redis/init" import { getWritethroughClient } from "../redis/init"
import { logWarn } from "../logging" import { logWarn } from "../logging"
import { PouchLike } from "../db" import { Database } from "@budibase/types"
const DEFAULT_WRITE_RATE_MS = 10000 const DEFAULT_WRITE_RATE_MS = 10000
let CACHE: BaseCache | null = null let CACHE: BaseCache | null = null
@ -19,7 +19,7 @@ async function getCache() {
return CACHE return CACHE
} }
function makeCacheKey(db: PouchLike, key: string) { function makeCacheKey(db: Database, key: string) {
return db.name + key return db.name + key
} }
@ -28,7 +28,7 @@ function makeCacheItem(doc: any, lastWrite: number | null = null): CacheItem {
} }
export async function put( export async function put(
db: PouchLike, db: Database,
doc: any, doc: any,
writeRateMs: number = DEFAULT_WRITE_RATE_MS writeRateMs: number = DEFAULT_WRITE_RATE_MS
) { ) {
@ -64,7 +64,7 @@ export async function put(
return { ok: true, id: output._id, rev: output._rev } return { ok: true, id: output._id, rev: output._rev }
} }
export async function get(db: PouchLike, id: string): Promise<any> { export async function get(db: Database, id: string): Promise<any> {
const cache = await getCache() const cache = await getCache()
const cacheKey = makeCacheKey(db, id) const cacheKey = makeCacheKey(db, id)
let cacheItem: CacheItem = await cache.get(cacheKey) let cacheItem: CacheItem = await cache.get(cacheKey)
@ -77,7 +77,7 @@ export async function get(db: PouchLike, id: string): Promise<any> {
} }
export async function remove( export async function remove(
db: PouchLike, db: Database,
docOrId: any, docOrId: any,
rev?: any rev?: any
): Promise<void> { ): Promise<void> {
@ -95,10 +95,10 @@ export async function remove(
} }
export class Writethrough { export class Writethrough {
db: PouchLike db: Database
writeRateMs: number writeRateMs: number
constructor(db: PouchLike, writeRateMs: number = DEFAULT_WRITE_RATE_MS) { constructor(db: Database, writeRateMs: number = DEFAULT_WRITE_RATE_MS) {
this.db = db this.db = db
this.writeRateMs = writeRateMs this.writeRateMs = writeRateMs
} }

View File

@ -3,17 +3,16 @@ import {
getAllApps, getAllApps,
doWithDB, doWithDB,
StaticDatabases, StaticDatabases,
PouchLike,
} from "../db" } from "../db"
import { doWithGlobalDB } from "../tenancy" import { doWithGlobalDB } from "../tenancy"
import { App, Tenants, User } from "@budibase/types" import { App, Tenants, User, Database } from "@budibase/types"
const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants const TENANT_DOC = StaticDatabases.PLATFORM_INFO.docs.tenants
const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name const PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name
async function removeTenantFromInfoDB(tenantId: string) { async function removeTenantFromInfoDB(tenantId: string) {
try { try {
await doWithDB(PLATFORM_INFO_DB, async (infoDb: PouchLike) => { await doWithDB(PLATFORM_INFO_DB, async (infoDb: Database) => {
const tenants = (await infoDb.get(TENANT_DOC)) as Tenants const tenants = (await infoDb.get(TENANT_DOC)) as Tenants
tenants.tenantIds = tenants.tenantIds.filter(id => id !== tenantId) tenants.tenantIds = tenants.tenantIds.filter(id => id !== tenantId)
@ -26,7 +25,7 @@ async function removeTenantFromInfoDB(tenantId: string) {
} }
export async function removeUserFromInfoDB(dbUser: User) { export async function removeUserFromInfoDB(dbUser: User) {
await doWithDB(PLATFORM_INFO_DB, async (infoDb: PouchLike) => { await doWithDB(PLATFORM_INFO_DB, async (infoDb: Database) => {
const keys = [dbUser._id!, dbUser.email] const keys = [dbUser._id!, dbUser.email]
const userDocs = await infoDb.allDocs({ const userDocs = await infoDb.allDocs({
keys, keys,
@ -77,7 +76,7 @@ async function removeUsersFromInfoDB(tenantId: string) {
} }
async function removeGlobalDB(tenantId: string) { async function removeGlobalDB(tenantId: string) {
return doWithGlobalDB(tenantId, async (db: PouchLike) => { return doWithGlobalDB(tenantId, async (db: Database) => {
try { try {
await db.destroy() await db.destroy()
} catch (err) { } catch (err) {
@ -91,7 +90,7 @@ async function removeTenantApps(tenantId: string) {
try { try {
const apps = (await getAllApps({ all: true })) as App[] const apps = (await getAllApps({ all: true })) as App[]
const destroyPromises = apps.map(app => const destroyPromises = apps.map(app =>
doWithDB(app.appId, (db: PouchLike) => db.destroy()) doWithDB(app.appId, (db: Database) => db.destroy())
) )
await Promise.allSettled(destroyPromises) await Promise.allSettled(destroyPromises)
} catch (err) { } catch (err) {

View File

@ -6,10 +6,9 @@ import {
getProdAppID, getProdAppID,
baseGlobalDBName, baseGlobalDBName,
getDB, getDB,
PouchLike,
} from "../db" } from "../db"
import Context from "./Context" import Context from "./Context"
import { IdentityContext } from "@budibase/types" import { IdentityContext, Database } from "@budibase/types"
import { DEFAULT_TENANT_ID as _DEFAULT_TENANT_ID } from "../constants" import { DEFAULT_TENANT_ID as _DEFAULT_TENANT_ID } from "../constants"
import { ContextMap } from "./constants" import { ContextMap } from "./constants"
export const DEFAULT_TENANT_ID = _DEFAULT_TENANT_ID export const DEFAULT_TENANT_ID = _DEFAULT_TENANT_ID
@ -182,7 +181,7 @@ export function updateAppId(appId: string) {
} }
} }
export function getGlobalDB(): PouchLike { export function getGlobalDB(): Database {
const context = Context.get() const context = Context.get()
if (!context || (env.MULTI_TENANCY && !context.tenantId)) { if (!context || (env.MULTI_TENANCY && !context.tenantId)) {
throw new Error("Global DB not found") throw new Error("Global DB not found")
@ -194,7 +193,7 @@ export function getGlobalDB(): PouchLike {
* Gets the app database based on whatever the request * Gets the app database based on whatever the request
* contained, dev or prod. * contained, dev or prod.
*/ */
export function getAppDB(opts?: any): PouchLike { export function getAppDB(opts?: any): Database {
const appId = getAppId() const appId = getAppId()
return getDB(appId, opts) return getDB(appId, opts)
} }
@ -203,7 +202,7 @@ export function getAppDB(opts?: any): PouchLike {
* This specifically gets the prod app ID, if the request * This specifically gets the prod app ID, if the request
* contained a development app ID, this will get the prod one. * contained a development app ID, this will get the prod one.
*/ */
export function getProdAppDB(opts?: any): PouchLike { export function getProdAppDB(opts?: any): Database {
const appId = getAppId() const appId = getAppId()
if (!appId) { if (!appId) {
throw new Error("Unable to retrieve prod DB - no app ID.") throw new Error("Unable to retrieve prod DB - no app ID.")
@ -215,7 +214,7 @@ export function getProdAppDB(opts?: any): PouchLike {
* This specifically gets the dev app ID, if the request * This specifically gets the dev app ID, if the request
* contained a prod app ID, this will get the dev one. * contained a prod app ID, this will get the dev one.
*/ */
export function getDevAppDB(opts?: any): PouchLike { export function getDevAppDB(opts?: any): Database {
const appId = getAppId() const appId = getAppId()
if (!appId) { if (!appId) {
throw new Error("Unable to retrieve dev DB - no app ID.") throw new Error("Unable to retrieve dev DB - no app ID.")

View File

@ -1,47 +1,35 @@
import Nano from "nano" import Nano from "nano"
import { AllDocsResponse, AnyDocument } from "@budibase/types" import {
AllDocsResponse,
AnyDocument,
Database,
DatabaseOpts,
DatabaseQueryOpts,
DatabasePutOpts,
} from "@budibase/types"
import { getCouchInfo } from "./connections" import { getCouchInfo } from "./connections"
import { directCouchCall } from "./utils" import { directCouchCall } from "./utils"
import { getPouchDB } from "./pouchDB" import { getPouchDB } from "./pouchDB"
export type PouchLikeOpts = { export class DatabaseImpl implements Database {
skip_setup?: boolean
}
export type PutOpts = {
force?: boolean
}
export type QueryOpts = {
include_docs?: boolean
startkey?: string
endkey?: string
limit?: number
skip?: number
descending?: boolean
key?: string
keys?: string[]
}
export class PouchLike {
public readonly name: string public readonly name: string
private static nano: Nano.ServerScope private static nano: Nano.ServerScope
private readonly pouchOpts: PouchLikeOpts private readonly pouchOpts: DatabaseOpts
constructor(dbName?: string, opts?: PouchLikeOpts) { constructor(dbName?: string, opts?: DatabaseOpts) {
if (dbName == null) { if (dbName == null) {
throw new Error("Database name cannot be undefined.") throw new Error("Database name cannot be undefined.")
} }
this.name = dbName this.name = dbName
this.pouchOpts = opts || {} this.pouchOpts = opts || {}
if (!PouchLike.nano) { if (!DatabaseImpl.nano) {
PouchLike.init() DatabaseImpl.init()
} }
} }
static init() { static init() {
const couchInfo = getCouchInfo() const couchInfo = getCouchInfo()
PouchLike.nano = Nano({ DatabaseImpl.nano = Nano({
url: couchInfo.url, url: couchInfo.url,
requestDefaults: { requestDefaults: {
headers: { headers: {
@ -65,9 +53,9 @@ export class PouchLike {
throw new Error("DB does not exist") throw new Error("DB does not exist")
} }
if (!exists) { if (!exists) {
await PouchLike.nano.db.create(this.name) await DatabaseImpl.nano.db.create(this.name)
} }
return PouchLike.nano.db.use(this.name) return DatabaseImpl.nano.db.use(this.name)
} }
private async updateOutput(fnc: any) { private async updateOutput(fnc: any) {
@ -97,7 +85,7 @@ export class PouchLike {
return this.updateOutput(() => db.destroy(id, rev)) return this.updateOutput(() => db.destroy(id, rev))
} }
async put(document: AnyDocument, opts?: PutOpts) { async put(document: AnyDocument, opts?: DatabasePutOpts) {
if (!document._id) { if (!document._id) {
throw new Error("Cannot store document without _id field.") throw new Error("Cannot store document without _id field.")
} }
@ -126,14 +114,14 @@ export class PouchLike {
return this.updateOutput(() => db.bulk({ docs: documents })) return this.updateOutput(() => db.bulk({ docs: documents }))
} }
async allDocs<T>(params: QueryOpts): Promise<AllDocsResponse<T>> { async allDocs<T>(params: DatabaseQueryOpts): Promise<AllDocsResponse<T>> {
const db = await this.checkSetup() const db = await this.checkSetup()
return this.updateOutput(() => db.list(params)) return this.updateOutput(() => db.list(params))
} }
async query<T>( async query<T>(
viewName: string, viewName: string,
params: QueryOpts params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>> { ): Promise<AllDocsResponse<T>> {
const db = await this.checkSetup() const db = await this.checkSetup()
const [database, view] = viewName.split("/") const [database, view] = viewName.split("/")
@ -142,7 +130,7 @@ export class PouchLike {
async destroy() { async destroy() {
try { try {
await PouchLike.nano.db.destroy(this.name) await DatabaseImpl.nano.db.destroy(this.name)
} catch (err: any) { } catch (err: any) {
// didn't exist, don't worry // didn't exist, don't worry
if (err.statusCode === 404) { if (err.statusCode === 404) {

View File

@ -1,4 +1,4 @@
export * from "./connections" export * from "./connections"
export * from "./PouchLike" export * from "./DatabaseImpl"
export * from "./utils" export * from "./utils"
export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB" export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB"

View File

@ -1,17 +1,18 @@
import env from "../environment" import env from "../environment"
import { directCouchQuery, PouchLike, getPouchDB } from "./couch" import { directCouchQuery, getPouchDB } from "./couch"
import { CouchFindOptions } from "@budibase/types" import { CouchFindOptions, Database } from "@budibase/types"
import { DatabaseImpl } from "../db"
const dbList = new Set() const dbList = new Set()
export function getDB(dbName?: string, opts?: any): PouchLike { export function getDB(dbName?: string, opts?: any): Database {
// TODO: once using the test image, need to remove this // TODO: once using the test image, need to remove this
if (env.isTest()) { if (env.isTest()) {
dbList.add(dbName) dbList.add(dbName)
// @ts-ignore // @ts-ignore
return getPouchDB(dbName, opts) return getPouchDB(dbName, opts)
} }
return new PouchLike(dbName, opts) return new DatabaseImpl(dbName, opts)
} }
// we have to use a callback for this so that we can close // we have to use a callback for this so that we can close

View File

@ -5,4 +5,3 @@ export * from "./views"
export * from "./constants" export * from "./constants"
export * from "./conversions" export * from "./conversions"
export * from "./tenancy" export * from "./tenancy"
export { PouchLike } from "./couch"

View File

@ -15,8 +15,7 @@ import { getAppMetadata } from "../cache/appMetadata"
import { isDevApp, isDevAppID, getProdAppID } from "./conversions" import { isDevApp, isDevAppID, getProdAppID } from "./conversions"
import { APP_PREFIX } from "./constants" import { APP_PREFIX } from "./constants"
import * as events from "../events" import * as events from "../events"
import { PouchLike } from "./couch" import { App, Database } from "@budibase/types"
import { App } from "@budibase/types"
export * from "./constants" export * from "./constants"
export * from "./conversions" export * from "./conversions"
@ -395,7 +394,7 @@ export async function getDevAppIDs() {
export async function dbExists(dbName: any) { export async function dbExists(dbName: any) {
return doWithDB( return doWithDB(
dbName, dbName,
async (db: PouchLike) => { async (db: Database) => {
return await db.exists() return await db.exists()
}, },
{ skip_setup: true } { skip_setup: true }

View File

@ -1,8 +1,8 @@
import { DocumentType, ViewName, DeprecatedViews, SEPARATOR } from "./utils" import { DocumentType, ViewName, DeprecatedViews, SEPARATOR } from "./utils"
import { getGlobalDB } from "../context" import { getGlobalDB } from "../context"
import { PouchLike, QueryOpts } from "./couch"
import { StaticDatabases } from "./constants" import { StaticDatabases } from "./constants"
import { doWithDB } from "./" import { doWithDB } from "./"
import { Database, DatabaseQueryOpts } from "@budibase/types"
const DESIGN_DB = "_design/database" const DESIGN_DB = "_design/database"
@ -19,7 +19,7 @@ interface DesignDocument {
views: any views: any
} }
async function removeDeprecated(db: PouchLike, viewName: ViewName) { async function removeDeprecated(db: Database, viewName: ViewName) {
// @ts-ignore // @ts-ignore
if (!DeprecatedViews[viewName]) { if (!DeprecatedViews[viewName]) {
return return
@ -70,7 +70,7 @@ export const createAccountEmailView = async () => {
emit(doc.email.toLowerCase(), doc._id) emit(doc.email.toLowerCase(), doc._id)
} }
}` }`
await doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: PouchLike) => { await doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: Database) => {
await createView(db, viewJs, ViewName.ACCOUNT_BY_EMAIL) await createView(db, viewJs, ViewName.ACCOUNT_BY_EMAIL)
}) })
} }
@ -114,7 +114,7 @@ export const createPlatformUserView = async () => {
emit(doc._id.toLowerCase(), doc._id) emit(doc._id.toLowerCase(), doc._id)
} }
}` }`
await doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: PouchLike) => { await doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: Database) => {
await createView(db, viewJs, ViewName.PLATFORM_USERS_LOWERCASE) await createView(db, viewJs, ViewName.PLATFORM_USERS_LOWERCASE)
}) })
} }
@ -125,8 +125,8 @@ export interface QueryViewOptions {
export const queryView = async <T>( export const queryView = async <T>(
viewName: ViewName, viewName: ViewName,
params: QueryOpts, params: DatabaseQueryOpts,
db: PouchLike, db: Database,
createFunc: any, createFunc: any,
opts?: QueryViewOptions opts?: QueryViewOptions
): Promise<T[] | T | undefined> => { ): Promise<T[] | T | undefined> => {
@ -157,7 +157,7 @@ export const queryView = async <T>(
export const queryPlatformView = async <T>( export const queryPlatformView = async <T>(
viewName: ViewName, viewName: ViewName,
params: QueryOpts, params: DatabaseQueryOpts,
opts?: QueryViewOptions opts?: QueryViewOptions
): Promise<T[] | T | undefined> => { ): Promise<T[] | T | undefined> => {
const CreateFuncByName: any = { const CreateFuncByName: any = {
@ -165,7 +165,7 @@ export const queryPlatformView = async <T>(
[ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView, [ViewName.PLATFORM_USERS_LOWERCASE]: createPlatformUserView,
} }
return doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: PouchLike) => { return doWithDB(StaticDatabases.PLATFORM_INFO.name, async (db: Database) => {
const createFn = CreateFuncByName[viewName] const createFn = CreateFuncByName[viewName]
return queryView(viewName, params, db, createFn, opts) return queryView(viewName, params, db, createFn, opts)
}) })
@ -173,8 +173,8 @@ export const queryPlatformView = async <T>(
export const queryGlobalView = async <T>( export const queryGlobalView = async <T>(
viewName: ViewName, viewName: ViewName,
params: QueryOpts, params: DatabaseQueryOpts,
db?: PouchLike, db?: Database,
opts?: QueryViewOptions opts?: QueryViewOptions
): Promise<T[] | T | undefined> => { ): Promise<T[] | T | undefined> => {
const CreateFuncByName: any = { const CreateFuncByName: any = {

View File

@ -9,13 +9,8 @@ import {
checkDebounce, checkDebounce,
setDebounce, setDebounce,
} from "../utilities/redis" } from "../utilities/redis"
import { import { db as dbCore, cache, permissions } from "@budibase/backend-core"
db as dbCore, import { BBContext, Database } from "@budibase/types"
cache,
permissions,
PouchLike,
} from "@budibase/backend-core"
import { BBContext } from "@budibase/types"
const DEBOUNCE_TIME_SEC = 30 const DEBOUNCE_TIME_SEC = 30
@ -55,7 +50,7 @@ async function updateAppUpdatedAt(ctx: BBContext) {
if (ctx.method === "GET" || (await checkDebounce(appId))) { if (ctx.method === "GET" || (await checkDebounce(appId))) {
return return
} }
await dbCore.doWithDB(appId, async (db: PouchLike) => { await dbCore.doWithDB(appId, async (db: Database) => {
const metadata = await db.get(DocumentType.APP_METADATA) const metadata = await db.get(DocumentType.APP_METADATA)
metadata.updatedAt = new Date().toISOString() metadata.updatedAt = new Date().toISOString()

View File

@ -1,10 +1,8 @@
import { events, PouchLike } from "@budibase/backend-core" import { events } from "@budibase/backend-core"
import { Database } from "@budibase/types"
import sdk from "../../../../sdk" import sdk from "../../../../sdk"
export const backfill = async ( export const backfill = async (appDb: Database, timestamp: string | number) => {
appDb: PouchLike,
timestamp: string | number
) => {
const tables = await sdk.tables.getAllInternalTables(appDb) const tables = await sdk.tables.getAllInternalTables(appDb)
for (const table of tables) { for (const table of tables) {

View File

@ -1,4 +1,5 @@
import { db as dbCore, PouchLike } from "@budibase/backend-core" import { db as dbCore } from "@budibase/backend-core"
import { Database } from "@budibase/types"
import { getAutomationParams, TABLE_ROW_PREFIX } from "../../../db/utils" import { getAutomationParams, TABLE_ROW_PREFIX } from "../../../db/utils"
import { budibaseTempDir } from "../../../utilities/budibaseDir" import { budibaseTempDir } from "../../../utilities/budibaseDir"
import { DB_EXPORT_FILE, GLOBAL_DB_EXPORT_FILE } from "./constants" import { DB_EXPORT_FILE, GLOBAL_DB_EXPORT_FILE } from "./constants"
@ -28,7 +29,7 @@ type TemplateType = {
key?: string key?: string
} }
async function updateAttachmentColumns(prodAppId: string, db: PouchLike) { async function updateAttachmentColumns(prodAppId: string, db: Database) {
// iterate through attachment documents and update them // iterate through attachment documents and update them
const tables = await sdk.tables.getAllInternalTables(db) const tables = await sdk.tables.getAllInternalTables(db)
for (let table of tables) { for (let table of tables) {
@ -82,7 +83,7 @@ async function updateAttachmentColumns(prodAppId: string, db: PouchLike) {
} }
} }
async function updateAutomations(prodAppId: string, db: PouchLike) { async function updateAutomations(prodAppId: string, db: Database) {
const automations = ( const automations = (
await db.allDocs( await db.allDocs(
getAutomationParams(null, { getAutomationParams(null, {
@ -150,7 +151,7 @@ export function getListOfAppsInMulti(tmpPath: string) {
export async function importApp( export async function importApp(
appId: string, appId: string,
db: PouchLike, db: Database,
template: TemplateType template: TemplateType
) { ) {
let prodAppId = dbCore.getProdAppID(appId) let prodAppId = dbCore.getProdAppID(appId)

View File

@ -1,4 +1,5 @@
import { context, db as dbCore, PouchLike } from "@budibase/backend-core" import { context, db as dbCore } from "@budibase/backend-core"
import { Database } from "@budibase/types"
import { import {
getDatasourceParams, getDatasourceParams,
getTableParams, getTableParams,
@ -6,7 +7,7 @@ import {
getScreenParams, getScreenParams,
} from "../../../db/utils" } from "../../../db/utils"
async function runInContext(appId: string, cb: any, db?: PouchLike) { async function runInContext(appId: string, cb: any, db?: Database) {
if (db) { if (db) {
return cb(db) return cb(db)
} else { } else {
@ -18,10 +19,10 @@ async function runInContext(appId: string, cb: any, db?: PouchLike) {
} }
} }
export async function calculateDatasourceCount(appId: string, db?: PouchLike) { export async function calculateDatasourceCount(appId: string, db?: Database) {
return runInContext( return runInContext(
appId, appId,
async (db: PouchLike) => { async (db: Database) => {
const datasourceList = await db.allDocs(getDatasourceParams()) const datasourceList = await db.allDocs(getDatasourceParams())
const tableList = await db.allDocs(getTableParams()) const tableList = await db.allDocs(getTableParams())
return datasourceList.rows.length + tableList.rows.length return datasourceList.rows.length + tableList.rows.length
@ -30,10 +31,10 @@ export async function calculateDatasourceCount(appId: string, db?: PouchLike) {
) )
} }
export async function calculateAutomationCount(appId: string, db?: PouchLike) { export async function calculateAutomationCount(appId: string, db?: Database) {
return runInContext( return runInContext(
appId, appId,
async (db: PouchLike) => { async (db: Database) => {
const automationList = await db.allDocs(getAutomationParams()) const automationList = await db.allDocs(getAutomationParams())
return automationList.rows.length return automationList.rows.length
}, },
@ -41,10 +42,10 @@ export async function calculateAutomationCount(appId: string, db?: PouchLike) {
) )
} }
export async function calculateScreenCount(appId: string, db?: PouchLike) { export async function calculateScreenCount(appId: string, db?: Database) {
return runInContext( return runInContext(
appId, appId,
async (db: PouchLike) => { async (db: Database) => {
const screenList = await db.allDocs(getScreenParams()) const screenList = await db.allDocs(getScreenParams())
return screenList.rows.length return screenList.rows.length
}, },
@ -53,7 +54,7 @@ export async function calculateScreenCount(appId: string, db?: PouchLike) {
} }
export async function calculateBackupStats(appId: string) { export async function calculateBackupStats(appId: string) {
return runInContext(appId, async (db: PouchLike) => { return runInContext(appId, async (db: Database) => {
const promises = [] const promises = []
promises.push(calculateDatasourceCount(appId, db)) promises.push(calculateDatasourceCount(appId, db))
promises.push(calculateAutomationCount(appId, db)) promises.push(calculateAutomationCount(appId, db))

View File

@ -1,13 +1,13 @@
import { context, PouchLike } from "@budibase/backend-core" import { context } from "@budibase/backend-core"
import { BudibaseInternalDB, getTableParams } from "../../../db/utils" import { BudibaseInternalDB, getTableParams } from "../../../db/utils"
import { import {
breakExternalTableId, breakExternalTableId,
isExternalTable, isExternalTable,
isSQL, isSQL,
} from "../../../integrations/utils" } from "../../../integrations/utils"
import { Table } from "@budibase/types" import { Table, Database } from "@budibase/types"
async function getAllInternalTables(db?: PouchLike): Promise<Table[]> { async function getAllInternalTables(db?: Database): Promise<Table[]> {
if (!db) { if (!db) {
db = context.getAppDB() db = context.getAppDB()
} }

View File

@ -17,6 +17,7 @@
"@types/node": "14.18.20", "@types/node": "14.18.20",
"@types/pouchdb": "6.4.0", "@types/pouchdb": "6.4.0",
"rimraf": "3.0.2", "rimraf": "3.0.2",
"typescript": "4.7.3" "typescript": "4.7.3",
"nano": "10.1.0"
} }
} }

View File

@ -1,4 +1,6 @@
import PouchDB from "pouchdb" import PouchDB from "pouchdb"
import Nano from "nano"
import { AllDocsResponse, AnyDocument } from "../"
export type PouchOptions = { export type PouchOptions = {
inMemory?: boolean inMemory?: boolean
@ -22,3 +24,50 @@ export type CouchFindOptions = {
skip?: number skip?: number
bookmark?: string bookmark?: string
} }
export type DatabaseOpts = {
skip_setup?: boolean
}
export type DatabasePutOpts = {
force?: boolean
}
export type DatabaseQueryOpts = {
include_docs?: boolean
startkey?: string
endkey?: string
limit?: number
skip?: number
descending?: boolean
key?: string
keys?: string[]
}
export interface Database {
name: string
exists(): Promise<boolean>
checkSetup(): Promise<Nano.DocumentScope<any>>
get<T>(id?: string): Promise<T | any>
remove(id?: string, rev?: string): Promise<Nano.DocumentDestroyResponse>
put(
document: AnyDocument,
opts?: DatabasePutOpts
): Promise<Nano.DocumentInsertResponse>
bulkDocs(documents: AnyDocument[]): Promise<Nano.DocumentBulkResponse>
allDocs<T>(params: DatabaseQueryOpts): Promise<AllDocsResponse<T>>
query<T>(
viewName: string,
params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>>
destroy(): Promise<Nano.OkResponse | void>
compact(): Promise<Nano.OkResponse | void>
// these are all PouchDB related functions that are rarely used - in future
// should be replaced by better typed/non-pouch implemented methods
dump(...args: any[]): Promise<any>
load(...args: any[]): Promise<any>
createIndex(...args: any[]): Promise<any>
deleteIndex(...args: any[]): Promise<any>
getIndexes(...args: any[]): Promise<any>
}

View File

@ -299,6 +299,32 @@
"@types/mime" "^1" "@types/mime" "^1"
"@types/node" "*" "@types/node" "*"
"@types/tough-cookie@^4.0.2":
version "4.0.2"
resolved "https://registry.yarnpkg.com/@types/tough-cookie/-/tough-cookie-4.0.2.tgz#6286b4c7228d58ab7866d19716f3696e03a09397"
integrity sha512-Q5vtl1W5ue16D+nIaW8JWebSSraJVlK+EthKn7e7UcD4KWsaSJ8BqGPXNaPghgtcn/fhvrN17Tv8ksUsQpiplw==
agent-base@^6.0.2:
version "6.0.2"
resolved "https://registry.yarnpkg.com/agent-base/-/agent-base-6.0.2.tgz#49fff58577cfee3f37176feab4c22e00f86d7f77"
integrity sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==
dependencies:
debug "4"
asynckit@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79"
integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==
axios@^1.1.3:
version "1.1.3"
resolved "https://registry.yarnpkg.com/axios/-/axios-1.1.3.tgz#8274250dada2edf53814ed7db644b9c2866c1e35"
integrity sha512-00tXVRwKx/FZr/IDVFt4C+f9FYairX517WoGCL6dpOntqLkZofjhu43F/Xl44UOpqa+9sLFDrG/XAnFsUYgkDA==
dependencies:
follow-redirects "^1.15.0"
form-data "^4.0.0"
proxy-from-env "^1.1.0"
balanced-match@^1.0.0: balanced-match@^1.0.0:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
@ -312,16 +338,71 @@ brace-expansion@^1.1.7:
balanced-match "^1.0.0" balanced-match "^1.0.0"
concat-map "0.0.1" concat-map "0.0.1"
call-bind@^1.0.0:
version "1.0.2"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c"
integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==
dependencies:
function-bind "^1.1.1"
get-intrinsic "^1.0.2"
combined-stream@^1.0.8:
version "1.0.8"
resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f"
integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==
dependencies:
delayed-stream "~1.0.0"
concat-map@0.0.1: concat-map@0.0.1:
version "0.0.1" version "0.0.1"
resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
debug@4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
dependencies:
ms "2.1.2"
delayed-stream@~1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619"
integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==
follow-redirects@^1.15.0:
version "1.15.2"
resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13"
integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
form-data@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452"
integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==
dependencies:
asynckit "^0.4.0"
combined-stream "^1.0.8"
mime-types "^2.1.12"
fs.realpath@^1.0.0: fs.realpath@^1.0.0:
version "1.0.0" version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
function-bind@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d"
integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==
get-intrinsic@^1.0.2:
version "1.1.3"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.3.tgz#063c84329ad93e83893c7f4f243ef63ffa351385"
integrity sha512-QJVz1Tj7MS099PevUG5jvnt9tSkXN8K14dxQlikJuPt4uD9hHAHjLyLBiLR5zELelBdD9QNRAXZzsJx0WaDL9A==
dependencies:
function-bind "^1.1.1"
has "^1.0.3"
has-symbols "^1.0.3"
glob@^7.1.3: glob@^7.1.3:
version "7.2.3" version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@ -334,6 +415,25 @@ glob@^7.1.3:
once "^1.3.0" once "^1.3.0"
path-is-absolute "^1.0.0" path-is-absolute "^1.0.0"
has-symbols@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8"
integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==
has@^1.0.3:
version "1.0.3"
resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796"
integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==
dependencies:
function-bind "^1.1.1"
http-cookie-agent@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/http-cookie-agent/-/http-cookie-agent-4.0.2.tgz#dcdaae18ed1f7452d81ae4d5cd80b227d6831b69"
integrity sha512-noTmxdH5CuytTnLj/Qv3Z84e/YFq8yLXAw3pqIYZ25Edhb9pQErIAC+ednw40Cic6Le/h9ryph5/TqsvkOaUCw==
dependencies:
agent-base "^6.0.2"
inflight@^1.0.4: inflight@^1.0.4:
version "1.0.6" version "1.0.6"
resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
@ -347,6 +447,18 @@ inherits@2:
resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==
mime-types@^2.1.12:
version "2.1.35"
resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a"
integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==
dependencies:
mime-db "1.52.0"
minimatch@^3.1.1: minimatch@^3.1.1:
version "3.1.2" version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@ -354,6 +466,33 @@ minimatch@^3.1.1:
dependencies: dependencies:
brace-expansion "^1.1.7" brace-expansion "^1.1.7"
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
nano@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/nano/-/nano-10.1.0.tgz#afdd5a7440e62f09a8e23f41fcea328d27383922"
integrity sha512-COeN2TpLcHuSN44QLnPmfZCoCsKAg8/aelPOVqqm/2/MvRHDEA11/Kld5C4sLzDlWlhFZ3SO2WGJGevCsvcEzQ==
dependencies:
"@types/tough-cookie" "^4.0.2"
axios "^1.1.3"
http-cookie-agent "^4.0.2"
node-abort-controller "^3.0.1"
qs "^6.11.0"
tough-cookie "^4.1.2"
node-abort-controller@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.0.1.tgz#f91fa50b1dee3f909afabb7e261b1e1d6b0cb74e"
integrity sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==
object-inspect@^1.9.0:
version "1.12.2"
resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.2.tgz#c0641f26394532f28ab8d796ab954e43c009a8ea"
integrity sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==
once@^1.3.0: once@^1.3.0:
version "1.4.0" version "1.4.0"
resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
@ -366,6 +505,38 @@ path-is-absolute@^1.0.0:
resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
proxy-from-env@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2"
integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==
psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
punycode@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
qs@^6.11.0:
version "6.11.0"
resolved "https://registry.yarnpkg.com/qs/-/qs-6.11.0.tgz#fd0d963446f7a65e1367e01abd85429453f0c37a"
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
dependencies:
side-channel "^1.0.4"
querystringify@^2.1.1:
version "2.2.0"
resolved "https://registry.yarnpkg.com/querystringify/-/querystringify-2.2.0.tgz#3345941b4153cb9d082d8eee4cda2016a9aef7f6"
integrity sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==
requires-port@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"
integrity sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==
rimraf@3.0.2: rimraf@3.0.2:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a"
@ -373,11 +544,43 @@ rimraf@3.0.2:
dependencies: dependencies:
glob "^7.1.3" glob "^7.1.3"
side-channel@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf"
integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==
dependencies:
call-bind "^1.0.0"
get-intrinsic "^1.0.2"
object-inspect "^1.9.0"
tough-cookie@^4.1.2:
version "4.1.2"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.1.2.tgz#e53e84b85f24e0b65dd526f46628db6c85f6b874"
integrity sha512-G9fqXWoYFZgTc2z8Q5zaHy/vJMjm+WV0AkAeHxVCQiEB1b+dGvWzFW6QV07cY5jQ5gRkeid2qIkzkxUnmoQZUQ==
dependencies:
psl "^1.1.33"
punycode "^2.1.1"
universalify "^0.2.0"
url-parse "^1.5.3"
typescript@4.7.3: typescript@4.7.3:
version "4.7.3" version "4.7.3"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d"
integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA== integrity sha512-WOkT3XYvrpXx4vMMqlD+8R8R37fZkjyLGlxavMc4iB8lrl8L0DeTcHbYgw/v0N/z9wAFsgBhcsF0ruoySS22mA==
universalify@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
integrity sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==
url-parse@^1.5.3:
version "1.5.10"
resolved "https://registry.yarnpkg.com/url-parse/-/url-parse-1.5.10.tgz#9d3c2f736c1d75dd3bd2be507dcc111f1e2ea9c1"
integrity sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==
dependencies:
querystringify "^2.1.1"
requires-port "^1.0.0"
wrappy@1: wrappy@1:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"

View File

@ -4,8 +4,8 @@ import { getTemplateByPurpose } from "../constants/templates"
import { getSettingsTemplateContext } from "./templates" import { getSettingsTemplateContext } from "./templates"
import { processString } from "@budibase/string-templates" import { processString } from "@budibase/string-templates"
import { getResetPasswordCode, getInviteCode } from "./redis" import { getResetPasswordCode, getInviteCode } from "./redis"
import { User } from "@budibase/types" import { User, Database } from "@budibase/types"
import { tenancy, db as dbCore, PouchLike } from "@budibase/backend-core" import { tenancy, db as dbCore } from "@budibase/backend-core"
const nodemailer = require("nodemailer") const nodemailer = require("nodemailer")
type SendEmailOpts = { type SendEmailOpts = {
@ -142,7 +142,7 @@ async function buildEmail(
* @return {Promise<object|null>} returns the SMTP configuration if it exists * @return {Promise<object|null>} returns the SMTP configuration if it exists
*/ */
async function getSmtpConfiguration( async function getSmtpConfiguration(
db: dbCore.PouchLike, db: Database,
workspaceId?: string, workspaceId?: string,
automation?: boolean automation?: boolean
) { ) {