Merge branch 'v3-ui' of github.com:Budibase/budibase into default-view-permissions

This commit is contained in:
Andrew Kingston 2024-09-25 10:01:54 +01:00
commit 496538ac01
No known key found for this signature in database
2 changed files with 38 additions and 9 deletions

View File

@ -11,6 +11,7 @@ export interface DeletedApp {
} }
const EXPIRY_SECONDS = 3600 const EXPIRY_SECONDS = 3600
const INVALID_EXPIRY_SECONDS = 60
/** /**
* The default populate app metadata function * The default populate app metadata function
@ -48,9 +49,8 @@ export async function getAppMetadata(appId: string): Promise<App | DeletedApp> {
// app DB left around, but no metadata, it is invalid // app DB left around, but no metadata, it is invalid
if (err && err.status === 404) { if (err && err.status === 404) {
metadata = { state: AppState.INVALID } metadata = { state: AppState.INVALID }
// don't expire the reference to an invalid app, it'll only be // expire invalid apps regularly, in-case it was only briefly invalid
// updated if a metadata doc actually gets stored (app is remade/reverted) expiry = INVALID_EXPIRY_SECONDS
expiry = undefined
} else { } else {
throw err throw err
} }

View File

@ -43,6 +43,9 @@ function buildNano(couchInfo: { url: string; cookie: string }) {
} }
type DBCall<T> = () => Promise<T> type DBCall<T> = () => Promise<T>
type DBCallback<T> = (
db: Nano.DocumentScope<any>
) => Promise<DBCall<T>> | DBCall<T>
class CouchDBError extends Error implements DBError { class CouchDBError extends Error implements DBError {
status: number status: number
@ -171,8 +174,8 @@ export class DatabaseImpl implements Database {
} }
// this function fetches the DB and handles if DB creation is needed // this function fetches the DB and handles if DB creation is needed
private async performCall<T>( private async performCallWithDBCreation<T>(
call: (db: Nano.DocumentScope<any>) => Promise<DBCall<T>> | DBCall<T> call: DBCallback<T>
): Promise<any> { ): Promise<any> {
const db = this.getDb() const db = this.getDb()
const fnc = await call(db) const fnc = await call(db)
@ -181,13 +184,24 @@ export class DatabaseImpl implements Database {
} catch (err: any) { } catch (err: any) {
if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) { if (err.statusCode === 404 && err.reason === DATABASE_NOT_FOUND) {
await this.checkAndCreateDb() await this.checkAndCreateDb()
return await this.performCall(call) return await this.performCallWithDBCreation(call)
} }
// stripping the error down the props which are safe/useful, drop everything else // stripping the error down the props which are safe/useful, drop everything else
throw new CouchDBError(`CouchDB error: ${err.message}`, err) throw new CouchDBError(`CouchDB error: ${err.message}`, err)
} }
} }
private async performCall<T>(call: DBCallback<T>): Promise<any> {
const db = this.getDb()
const fnc = await call(db)
try {
return await fnc()
} catch (err: any) {
// stripping the error down the props which are safe/useful, drop everything else
throw new CouchDBError(`CouchDB error: ${err.message}`, err)
}
}
async get<T extends Document>(id?: string): Promise<T> { async get<T extends Document>(id?: string): Promise<T> {
return this.performCall(db => { return this.performCall(db => {
if (!id) { if (!id) {
@ -227,6 +241,7 @@ export class DatabaseImpl implements Database {
} }
async remove(idOrDoc: string | Document, rev?: string) { async remove(idOrDoc: string | Document, rev?: string) {
// not a read call - but don't create a DB to delete a document
return this.performCall(db => { return this.performCall(db => {
let _id: string let _id: string
let _rev: string let _rev: string
@ -286,7 +301,7 @@ export class DatabaseImpl implements Database {
if (!document._id) { if (!document._id) {
throw new Error("Cannot store document without _id field.") throw new Error("Cannot store document without _id field.")
} }
return this.performCall(async db => { return this.performCallWithDBCreation(async db => {
if (!document.createdAt) { if (!document.createdAt) {
document.createdAt = new Date().toISOString() document.createdAt = new Date().toISOString()
} }
@ -309,7 +324,7 @@ export class DatabaseImpl implements Database {
async bulkDocs(documents: AnyDocument[]) { async bulkDocs(documents: AnyDocument[]) {
const now = new Date().toISOString() const now = new Date().toISOString()
return this.performCall(db => { return this.performCallWithDBCreation(db => {
return () => return () =>
db.bulk({ db.bulk({
docs: documents.map(d => ({ createdAt: now, ...d, updatedAt: now })), docs: documents.map(d => ({ createdAt: now, ...d, updatedAt: now })),
@ -321,7 +336,21 @@ export class DatabaseImpl implements Database {
params: DatabaseQueryOpts params: DatabaseQueryOpts
): Promise<AllDocsResponse<T>> { ): Promise<AllDocsResponse<T>> {
return this.performCall(db => { return this.performCall(db => {
return () => db.list(params) return async () => {
try {
return (await db.list(params)) as AllDocsResponse<T>
} catch (err: any) {
if (err.reason === DATABASE_NOT_FOUND) {
return {
offset: 0,
total_rows: 0,
rows: [],
}
} else {
throw err
}
}
}
}) })
} }