From c4f041e511c47350105f68b5475d9b540c551cc5 Mon Sep 17 00:00:00 2001 From: mike12345567 Date: Thu, 17 Nov 2022 14:35:03 +0000 Subject: [PATCH] Updating PouchLike to be an interface in types, with its impl stored in backend-core, now called Database. --- .../backend-core/src/cache/writethrough.ts | 14 +- .../backend-core/src/context/deprovision.ts | 11 +- packages/backend-core/src/context/index.ts | 11 +- .../couch/{PouchLike.ts => DatabaseImpl.ts} | 52 ++--- packages/backend-core/src/db/couch/index.ts | 2 +- packages/backend-core/src/db/db.ts | 9 +- packages/backend-core/src/db/index.ts | 1 - packages/backend-core/src/db/utils.ts | 5 +- packages/backend-core/src/db/views.ts | 20 +- packages/server/src/middleware/builder.ts | 11 +- .../functions/backfill/app/tables.ts | 8 +- .../server/src/sdk/app/backups/imports.ts | 9 +- .../server/src/sdk/app/backups/statistics.ts | 19 +- packages/server/src/sdk/app/tables/index.ts | 6 +- packages/types/package.json | 3 +- packages/types/src/sdk/db.ts | 49 +++++ packages/types/yarn.lock | 203 ++++++++++++++++++ packages/worker/src/utilities/email.ts | 6 +- 18 files changed, 336 insertions(+), 103 deletions(-) rename packages/backend-core/src/db/couch/{PouchLike.ts => DatabaseImpl.ts} (82%) diff --git a/packages/backend-core/src/cache/writethrough.ts b/packages/backend-core/src/cache/writethrough.ts index e13cc8cc0d..dc889d5b18 100644 --- a/packages/backend-core/src/cache/writethrough.ts +++ b/packages/backend-core/src/cache/writethrough.ts @@ -1,7 +1,7 @@ import BaseCache from "./base" import { getWritethroughClient } from "../redis/init" import { logWarn } from "../logging" -import { PouchLike } from "../db" +import { Database } from "@budibase/types" const DEFAULT_WRITE_RATE_MS = 10000 let CACHE: BaseCache | null = null @@ -19,7 +19,7 @@ async function getCache() { return CACHE } -function makeCacheKey(db: PouchLike, key: string) { +function makeCacheKey(db: Database, key: string) { return db.name + key } @@ -28,7 +28,7 @@ function makeCacheItem(doc: any, lastWrite: number | null = null): CacheItem { } export async function put( - db: PouchLike, + db: Database, doc: any, writeRateMs: number = DEFAULT_WRITE_RATE_MS ) { @@ -64,7 +64,7 @@ export async function put( return { ok: true, id: output._id, rev: output._rev } } -export async function get(db: PouchLike, id: string): Promise { +export async function get(db: Database, id: string): Promise { const cache = await getCache() const cacheKey = makeCacheKey(db, id) let cacheItem: CacheItem = await cache.get(cacheKey) @@ -77,7 +77,7 @@ export async function get(db: PouchLike, id: string): Promise { } export async function remove( - db: PouchLike, + db: Database, docOrId: any, rev?: any ): Promise { @@ -95,10 +95,10 @@ export async function remove( } export class Writethrough { - db: PouchLike + db: Database writeRateMs: number - constructor(db: PouchLike, writeRateMs: number = DEFAULT_WRITE_RATE_MS) { + constructor(db: Database, writeRateMs: number = DEFAULT_WRITE_RATE_MS) { this.db = db this.writeRateMs = writeRateMs } diff --git a/packages/backend-core/src/context/deprovision.ts b/packages/backend-core/src/context/deprovision.ts index 6f397f60d0..81f03096dc 100644 --- a/packages/backend-core/src/context/deprovision.ts +++ b/packages/backend-core/src/context/deprovision.ts @@ -3,17 +3,16 @@ import { getAllApps, doWithDB, StaticDatabases, - PouchLike, } from "../db" 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 PLATFORM_INFO_DB = StaticDatabases.PLATFORM_INFO.name async function removeTenantFromInfoDB(tenantId: string) { 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 tenants.tenantIds = tenants.tenantIds.filter(id => id !== tenantId) @@ -26,7 +25,7 @@ async function removeTenantFromInfoDB(tenantId: string) { } 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 userDocs = await infoDb.allDocs({ keys, @@ -77,7 +76,7 @@ async function removeUsersFromInfoDB(tenantId: string) { } async function removeGlobalDB(tenantId: string) { - return doWithGlobalDB(tenantId, async (db: PouchLike) => { + return doWithGlobalDB(tenantId, async (db: Database) => { try { await db.destroy() } catch (err) { @@ -91,7 +90,7 @@ async function removeTenantApps(tenantId: string) { try { const apps = (await getAllApps({ all: true })) as App[] const destroyPromises = apps.map(app => - doWithDB(app.appId, (db: PouchLike) => db.destroy()) + doWithDB(app.appId, (db: Database) => db.destroy()) ) await Promise.allSettled(destroyPromises) } catch (err) { diff --git a/packages/backend-core/src/context/index.ts b/packages/backend-core/src/context/index.ts index 3499082f6a..ce37d4f0b4 100644 --- a/packages/backend-core/src/context/index.ts +++ b/packages/backend-core/src/context/index.ts @@ -6,10 +6,9 @@ import { getProdAppID, baseGlobalDBName, getDB, - PouchLike, } from "../db" 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 { ContextMap } from "./constants" 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() if (!context || (env.MULTI_TENANCY && !context.tenantId)) { throw new Error("Global DB not found") @@ -194,7 +193,7 @@ export function getGlobalDB(): PouchLike { * Gets the app database based on whatever the request * contained, dev or prod. */ -export function getAppDB(opts?: any): PouchLike { +export function getAppDB(opts?: any): Database { const appId = getAppId() return getDB(appId, opts) } @@ -203,7 +202,7 @@ export function getAppDB(opts?: any): PouchLike { * This specifically gets the prod app ID, if the request * 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() if (!appId) { 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 * 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() if (!appId) { throw new Error("Unable to retrieve dev DB - no app ID.") diff --git a/packages/backend-core/src/db/couch/PouchLike.ts b/packages/backend-core/src/db/couch/DatabaseImpl.ts similarity index 82% rename from packages/backend-core/src/db/couch/PouchLike.ts rename to packages/backend-core/src/db/couch/DatabaseImpl.ts index 975bbd96c4..d7220e845c 100644 --- a/packages/backend-core/src/db/couch/PouchLike.ts +++ b/packages/backend-core/src/db/couch/DatabaseImpl.ts @@ -1,47 +1,35 @@ 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 { directCouchCall } from "./utils" import { getPouchDB } from "./pouchDB" -export type PouchLikeOpts = { - 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 { +export class DatabaseImpl implements Database { public readonly name: string 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) { throw new Error("Database name cannot be undefined.") } this.name = dbName this.pouchOpts = opts || {} - if (!PouchLike.nano) { - PouchLike.init() + if (!DatabaseImpl.nano) { + DatabaseImpl.init() } } static init() { const couchInfo = getCouchInfo() - PouchLike.nano = Nano({ + DatabaseImpl.nano = Nano({ url: couchInfo.url, requestDefaults: { headers: { @@ -65,9 +53,9 @@ export class PouchLike { throw new Error("DB does not exist") } 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) { @@ -97,7 +85,7 @@ export class PouchLike { return this.updateOutput(() => db.destroy(id, rev)) } - async put(document: AnyDocument, opts?: PutOpts) { + async put(document: AnyDocument, opts?: DatabasePutOpts) { if (!document._id) { throw new Error("Cannot store document without _id field.") } @@ -126,14 +114,14 @@ export class PouchLike { return this.updateOutput(() => db.bulk({ docs: documents })) } - async allDocs(params: QueryOpts): Promise> { + async allDocs(params: DatabaseQueryOpts): Promise> { const db = await this.checkSetup() return this.updateOutput(() => db.list(params)) } async query( viewName: string, - params: QueryOpts + params: DatabaseQueryOpts ): Promise> { const db = await this.checkSetup() const [database, view] = viewName.split("/") @@ -142,7 +130,7 @@ export class PouchLike { async destroy() { try { - await PouchLike.nano.db.destroy(this.name) + await DatabaseImpl.nano.db.destroy(this.name) } catch (err: any) { // didn't exist, don't worry if (err.statusCode === 404) { diff --git a/packages/backend-core/src/db/couch/index.ts b/packages/backend-core/src/db/couch/index.ts index ea47022c35..c731d20d6c 100644 --- a/packages/backend-core/src/db/couch/index.ts +++ b/packages/backend-core/src/db/couch/index.ts @@ -1,4 +1,4 @@ export * from "./connections" -export * from "./PouchLike" +export * from "./DatabaseImpl" export * from "./utils" export { init, getPouch, getPouchDB, closePouchDB } from "./pouchDB" diff --git a/packages/backend-core/src/db/db.ts b/packages/backend-core/src/db/db.ts index beaea3d42c..3887e8b09f 100644 --- a/packages/backend-core/src/db/db.ts +++ b/packages/backend-core/src/db/db.ts @@ -1,17 +1,18 @@ import env from "../environment" -import { directCouchQuery, PouchLike, getPouchDB } from "./couch" -import { CouchFindOptions } from "@budibase/types" +import { directCouchQuery, getPouchDB } from "./couch" +import { CouchFindOptions, Database } from "@budibase/types" +import { DatabaseImpl } from "../db" 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 if (env.isTest()) { dbList.add(dbName) // @ts-ignore 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 diff --git a/packages/backend-core/src/db/index.ts b/packages/backend-core/src/db/index.ts index 3db29a905f..7269aa8f92 100644 --- a/packages/backend-core/src/db/index.ts +++ b/packages/backend-core/src/db/index.ts @@ -5,4 +5,3 @@ export * from "./views" export * from "./constants" export * from "./conversions" export * from "./tenancy" -export { PouchLike } from "./couch" diff --git a/packages/backend-core/src/db/utils.ts b/packages/backend-core/src/db/utils.ts index 76e011735e..076552beec 100644 --- a/packages/backend-core/src/db/utils.ts +++ b/packages/backend-core/src/db/utils.ts @@ -15,8 +15,7 @@ import { getAppMetadata } from "../cache/appMetadata" import { isDevApp, isDevAppID, getProdAppID } from "./conversions" import { APP_PREFIX } from "./constants" import * as events from "../events" -import { PouchLike } from "./couch" -import { App } from "@budibase/types" +import { App, Database } from "@budibase/types" export * from "./constants" export * from "./conversions" @@ -395,7 +394,7 @@ export async function getDevAppIDs() { export async function dbExists(dbName: any) { return doWithDB( dbName, - async (db: PouchLike) => { + async (db: Database) => { return await db.exists() }, { skip_setup: true } diff --git a/packages/backend-core/src/db/views.ts b/packages/backend-core/src/db/views.ts index 23771d3f2d..5c63ce4689 100644 --- a/packages/backend-core/src/db/views.ts +++ b/packages/backend-core/src/db/views.ts @@ -1,8 +1,8 @@ import { DocumentType, ViewName, DeprecatedViews, SEPARATOR } from "./utils" import { getGlobalDB } from "../context" -import { PouchLike, QueryOpts } from "./couch" import { StaticDatabases } from "./constants" import { doWithDB } from "./" +import { Database, DatabaseQueryOpts } from "@budibase/types" const DESIGN_DB = "_design/database" @@ -19,7 +19,7 @@ interface DesignDocument { views: any } -async function removeDeprecated(db: PouchLike, viewName: ViewName) { +async function removeDeprecated(db: Database, viewName: ViewName) { // @ts-ignore if (!DeprecatedViews[viewName]) { return @@ -70,7 +70,7 @@ export const createAccountEmailView = async () => { 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) }) } @@ -114,7 +114,7 @@ export const createPlatformUserView = async () => { 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) }) } @@ -125,8 +125,8 @@ export interface QueryViewOptions { export const queryView = async ( viewName: ViewName, - params: QueryOpts, - db: PouchLike, + params: DatabaseQueryOpts, + db: Database, createFunc: any, opts?: QueryViewOptions ): Promise => { @@ -157,7 +157,7 @@ export const queryView = async ( export const queryPlatformView = async ( viewName: ViewName, - params: QueryOpts, + params: DatabaseQueryOpts, opts?: QueryViewOptions ): Promise => { const CreateFuncByName: any = { @@ -165,7 +165,7 @@ export const queryPlatformView = async ( [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] return queryView(viewName, params, db, createFn, opts) }) @@ -173,8 +173,8 @@ export const queryPlatformView = async ( export const queryGlobalView = async ( viewName: ViewName, - params: QueryOpts, - db?: PouchLike, + params: DatabaseQueryOpts, + db?: Database, opts?: QueryViewOptions ): Promise => { const CreateFuncByName: any = { diff --git a/packages/server/src/middleware/builder.ts b/packages/server/src/middleware/builder.ts index 719a4dc060..b53f2903b7 100644 --- a/packages/server/src/middleware/builder.ts +++ b/packages/server/src/middleware/builder.ts @@ -9,13 +9,8 @@ import { checkDebounce, setDebounce, } from "../utilities/redis" -import { - db as dbCore, - cache, - permissions, - PouchLike, -} from "@budibase/backend-core" -import { BBContext } from "@budibase/types" +import { db as dbCore, cache, permissions } from "@budibase/backend-core" +import { BBContext, Database } from "@budibase/types" const DEBOUNCE_TIME_SEC = 30 @@ -55,7 +50,7 @@ async function updateAppUpdatedAt(ctx: BBContext) { if (ctx.method === "GET" || (await checkDebounce(appId))) { return } - await dbCore.doWithDB(appId, async (db: PouchLike) => { + await dbCore.doWithDB(appId, async (db: Database) => { const metadata = await db.get(DocumentType.APP_METADATA) metadata.updatedAt = new Date().toISOString() diff --git a/packages/server/src/migrations/functions/backfill/app/tables.ts b/packages/server/src/migrations/functions/backfill/app/tables.ts index c9d1e5c794..51b0de5d29 100644 --- a/packages/server/src/migrations/functions/backfill/app/tables.ts +++ b/packages/server/src/migrations/functions/backfill/app/tables.ts @@ -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" -export const backfill = async ( - appDb: PouchLike, - timestamp: string | number -) => { +export const backfill = async (appDb: Database, timestamp: string | number) => { const tables = await sdk.tables.getAllInternalTables(appDb) for (const table of tables) { diff --git a/packages/server/src/sdk/app/backups/imports.ts b/packages/server/src/sdk/app/backups/imports.ts index 634f507220..998ffe9241 100644 --- a/packages/server/src/sdk/app/backups/imports.ts +++ b/packages/server/src/sdk/app/backups/imports.ts @@ -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 { budibaseTempDir } from "../../../utilities/budibaseDir" import { DB_EXPORT_FILE, GLOBAL_DB_EXPORT_FILE } from "./constants" @@ -28,7 +29,7 @@ type TemplateType = { key?: string } -async function updateAttachmentColumns(prodAppId: string, db: PouchLike) { +async function updateAttachmentColumns(prodAppId: string, db: Database) { // iterate through attachment documents and update them const tables = await sdk.tables.getAllInternalTables(db) 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 = ( await db.allDocs( getAutomationParams(null, { @@ -150,7 +151,7 @@ export function getListOfAppsInMulti(tmpPath: string) { export async function importApp( appId: string, - db: PouchLike, + db: Database, template: TemplateType ) { let prodAppId = dbCore.getProdAppID(appId) diff --git a/packages/server/src/sdk/app/backups/statistics.ts b/packages/server/src/sdk/app/backups/statistics.ts index 9fe1a04d21..aecb3de423 100644 --- a/packages/server/src/sdk/app/backups/statistics.ts +++ b/packages/server/src/sdk/app/backups/statistics.ts @@ -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 { getDatasourceParams, getTableParams, @@ -6,7 +7,7 @@ import { getScreenParams, } from "../../../db/utils" -async function runInContext(appId: string, cb: any, db?: PouchLike) { +async function runInContext(appId: string, cb: any, db?: Database) { if (db) { return cb(db) } 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( appId, - async (db: PouchLike) => { + async (db: Database) => { const datasourceList = await db.allDocs(getDatasourceParams()) const tableList = await db.allDocs(getTableParams()) 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( appId, - async (db: PouchLike) => { + async (db: Database) => { const automationList = await db.allDocs(getAutomationParams()) 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( appId, - async (db: PouchLike) => { + async (db: Database) => { const screenList = await db.allDocs(getScreenParams()) return screenList.rows.length }, @@ -53,7 +54,7 @@ export async function calculateScreenCount(appId: string, db?: PouchLike) { } export async function calculateBackupStats(appId: string) { - return runInContext(appId, async (db: PouchLike) => { + return runInContext(appId, async (db: Database) => { const promises = [] promises.push(calculateDatasourceCount(appId, db)) promises.push(calculateAutomationCount(appId, db)) diff --git a/packages/server/src/sdk/app/tables/index.ts b/packages/server/src/sdk/app/tables/index.ts index ef41630d6b..15bf02cf62 100644 --- a/packages/server/src/sdk/app/tables/index.ts +++ b/packages/server/src/sdk/app/tables/index.ts @@ -1,13 +1,13 @@ -import { context, PouchLike } from "@budibase/backend-core" +import { context } from "@budibase/backend-core" import { BudibaseInternalDB, getTableParams } from "../../../db/utils" import { breakExternalTableId, isExternalTable, isSQL, } from "../../../integrations/utils" -import { Table } from "@budibase/types" +import { Table, Database } from "@budibase/types" -async function getAllInternalTables(db?: PouchLike): Promise { +async function getAllInternalTables(db?: Database): Promise { if (!db) { db = context.getAppDB() } diff --git a/packages/types/package.json b/packages/types/package.json index 2978e8b6c1..6d67753d7f 100644 --- a/packages/types/package.json +++ b/packages/types/package.json @@ -17,6 +17,7 @@ "@types/node": "14.18.20", "@types/pouchdb": "6.4.0", "rimraf": "3.0.2", - "typescript": "4.7.3" + "typescript": "4.7.3", + "nano": "10.1.0" } } diff --git a/packages/types/src/sdk/db.ts b/packages/types/src/sdk/db.ts index b3e51d2dff..9d2ed9c21c 100644 --- a/packages/types/src/sdk/db.ts +++ b/packages/types/src/sdk/db.ts @@ -1,4 +1,6 @@ import PouchDB from "pouchdb" +import Nano from "nano" +import { AllDocsResponse, AnyDocument } from "../" export type PouchOptions = { inMemory?: boolean @@ -22,3 +24,50 @@ export type CouchFindOptions = { skip?: number 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 + checkSetup(): Promise> + get(id?: string): Promise + remove(id?: string, rev?: string): Promise + put( + document: AnyDocument, + opts?: DatabasePutOpts + ): Promise + bulkDocs(documents: AnyDocument[]): Promise + allDocs(params: DatabaseQueryOpts): Promise> + query( + viewName: string, + params: DatabaseQueryOpts + ): Promise> + destroy(): Promise + compact(): Promise + // 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 + load(...args: any[]): Promise + createIndex(...args: any[]): Promise + deleteIndex(...args: any[]): Promise + getIndexes(...args: any[]): Promise +} diff --git a/packages/types/yarn.lock b/packages/types/yarn.lock index f225ffc442..98e5845121 100644 --- a/packages/types/yarn.lock +++ b/packages/types/yarn.lock @@ -299,6 +299,32 @@ "@types/mime" "^1" "@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: version "1.0.2" 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" 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: version "0.0.1" resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 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: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 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: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -334,6 +415,25 @@ glob@^7.1.3: once "^1.3.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: version "1.0.6" 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" 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: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -354,6 +466,33 @@ minimatch@^3.1.1: dependencies: 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: version "1.4.0" 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" 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: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -373,11 +544,43 @@ rimraf@3.0.2: dependencies: 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: version "4.7.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" 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: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" diff --git a/packages/worker/src/utilities/email.ts b/packages/worker/src/utilities/email.ts index e71109c0b8..7ec3447707 100644 --- a/packages/worker/src/utilities/email.ts +++ b/packages/worker/src/utilities/email.ts @@ -4,8 +4,8 @@ import { getTemplateByPurpose } from "../constants/templates" import { getSettingsTemplateContext } from "./templates" import { processString } from "@budibase/string-templates" import { getResetPasswordCode, getInviteCode } from "./redis" -import { User } from "@budibase/types" -import { tenancy, db as dbCore, PouchLike } from "@budibase/backend-core" +import { User, Database } from "@budibase/types" +import { tenancy, db as dbCore } from "@budibase/backend-core" const nodemailer = require("nodemailer") type SendEmailOpts = { @@ -142,7 +142,7 @@ async function buildEmail( * @return {Promise} returns the SMTP configuration if it exists */ async function getSmtpConfiguration( - db: dbCore.PouchLike, + db: Database, workspaceId?: string, automation?: boolean ) {