UNPKG

@budibase/server

Version:
187 lines (176 loc) • 5.13 kB
import { context } from "@budibase/backend-core" import { Database, DBView, DesignDocument, DocumentType, InMemoryView, } from "@budibase/types" import { generateMemoryViewID, getMemoryViewParams, SEPARATOR, ViewName, } from "../../../db/utils" import env from "../../../environment" import viewBuilder from "./viewBuilder" export async function getView(viewName: string) { const db = context.getWorkspaceDB() if (env.SELF_HOSTED) { const designDoc = await db.get<DesignDocument>("_design/database") return designDoc.views?.[viewName] } else { // This is a table view, don't read the view from the DB if (viewName.startsWith(DocumentType.TABLE + SEPARATOR)) { return null } try { const viewDoc = await db.get<InMemoryView>(generateMemoryViewID(viewName)) return viewDoc.view } catch (err: any) { // Return null when PouchDB doesn't found the view if (err.status === 404) { return null } throw err } } } export async function getViews(): Promise<DBView[]> { const db = context.getWorkspaceDB() const response: DBView[] = [] if (env.SELF_HOSTED) { const designDoc = await db.get<DesignDocument>("_design/database") for (let name of Object.keys(designDoc.views || {})) { // Only return custom views, not built ins const viewNames = Object.values(ViewName) as string[] if (viewNames.indexOf(name) !== -1) { continue } const view = designDoc.views?.[name] if (view) { response.push({ name, ...view, }) } } } else { const views = ( await db.allDocs<InMemoryView>( getMemoryViewParams({ include_docs: true, }) ) ).rows.map(row => row.doc!) for (let viewDoc of views) { response.push({ name: viewDoc.name, ...viewDoc.view, }) } } return response } export async function saveView( originalName: string | null, viewName: string, viewTemplate: DBView ) { const db = context.getWorkspaceDB() if (env.SELF_HOSTED) { const designDoc = await db.get<DesignDocument>("_design/database") designDoc.views = { ...designDoc.views, [viewName]: viewTemplate, } // view has been renamed if (originalName) { delete designDoc.views[originalName] } await db.put(designDoc) } else { const id = generateMemoryViewID(viewName) const originalId = originalName ? generateMemoryViewID(originalName) : null const viewDoc: InMemoryView = { _id: id, view: viewTemplate, name: viewName, tableId: viewTemplate.meta!.tableId, } try { const old = await db.get<InMemoryView>(id) if (originalId) { const originalDoc = await db.get<InMemoryView>(originalId) await db.remove(originalDoc._id!, originalDoc._rev) } if (old && old._rev) { viewDoc._rev = old._rev } } catch (err) { // didn't exist, just skip } await db.put(viewDoc) } } export async function deleteView(viewName: string) { const db = context.getWorkspaceDB() if (env.SELF_HOSTED) { const designDoc = await db.get<DesignDocument>("_design/database") const view = designDoc.views?.[viewName] delete designDoc.views?.[viewName] await db.put(designDoc) return view } else { const id = generateMemoryViewID(viewName) const viewDoc = await db.get<InMemoryView>(id) await db.remove(viewDoc._id!, viewDoc._rev) return viewDoc.view } } export async function migrateToInMemoryView(db: Database, viewName: string) { // delete the view initially const designDoc = await db.get<DesignDocument>("_design/database") const meta = designDoc.views?.[viewName].meta if (!meta) { throw new Error("Unable to migrate view - no metadata") } // run the view back through the view builder to update it const view = viewBuilder(meta) delete designDoc.views?.[viewName] await db.put(designDoc) await saveView(null, viewName, view) } export async function migrateToDesignView(db: Database, viewName: string) { let view = await db.get<InMemoryView>(generateMemoryViewID(viewName)) const designDoc = await db.get<DesignDocument>("_design/database") const meta = view.view.meta if (!meta) { throw new Error("Unable to migrate view - no metadata") } if (!designDoc.views) { designDoc.views = {} } designDoc.views[viewName] = viewBuilder(meta) await db.put(designDoc) await db.remove(view._id!, view._rev) } export async function getFromDesignDoc(db: Database, viewName: string) { const designDoc = await db.get<DesignDocument>("_design/database") let view = designDoc.views?.[viewName] if (view == null) { throw { status: 404, message: "Unable to get view" } } return view } export async function getFromMemoryDoc( db: Database, viewName: string ): Promise<DBView> { let view = await db.get<InMemoryView>(generateMemoryViewID(viewName)) if (view) { return view.view } else { throw { status: 404, message: "Unable to get view" } } }