Simplify errors framework (#10042)
* Simplify errors framework * Use enum for ErrorCode * Lint * Update base BudibaseError type to use enum * For for public error on UsageLimitError * Build fix * Build fix
This commit is contained in:
parent
f065f9b621
commit
de89b9112a
|
@ -1,10 +0,0 @@
|
||||||
export class BudibaseError extends Error {
|
|
||||||
code: string
|
|
||||||
type: string
|
|
||||||
|
|
||||||
constructor(message: string, code: string, type: string) {
|
|
||||||
super(message)
|
|
||||||
this.code = code
|
|
||||||
this.type = type
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,37 +1,87 @@
|
||||||
import * as licensing from "./licensing"
|
// BASE
|
||||||
|
|
||||||
// combine all error codes into single object
|
export abstract class BudibaseError extends Error {
|
||||||
|
code: string
|
||||||
|
|
||||||
export const codes = {
|
constructor(message: string, code: ErrorCode) {
|
||||||
...licensing.codes,
|
super(message)
|
||||||
|
this.code = code
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPublicError?(): any
|
||||||
}
|
}
|
||||||
|
|
||||||
// combine all error types
|
// ERROR HANDLING
|
||||||
export const types = [licensing.type]
|
|
||||||
|
|
||||||
// combine all error contexts
|
export enum ErrorCode {
|
||||||
const context = {
|
USAGE_LIMIT_EXCEEDED = "usage_limit_exceeded",
|
||||||
...licensing.context,
|
FEATURE_DISABLED = "feature_disabled",
|
||||||
|
HTTP = "http",
|
||||||
}
|
}
|
||||||
|
|
||||||
// derive a public error message using codes, types and any custom contexts
|
/**
|
||||||
|
* For the given error, build the public representation that is safe
|
||||||
|
* to be exposed over an api.
|
||||||
|
*/
|
||||||
export const getPublicError = (err: any) => {
|
export const getPublicError = (err: any) => {
|
||||||
let error
|
let error
|
||||||
if (err.code || err.type) {
|
if (err.code) {
|
||||||
// add generic error information
|
// add generic error information
|
||||||
error = {
|
error = {
|
||||||
code: err.code,
|
code: err.code,
|
||||||
type: err.type,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (err.code && context[err.code]) {
|
if (err.getPublicError) {
|
||||||
error = {
|
error = {
|
||||||
...error,
|
...error,
|
||||||
// get any additional context from this error
|
// get any additional context from this error
|
||||||
...context[err.code](err),
|
...err.getPublicError(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return error
|
return error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HTTP
|
||||||
|
|
||||||
|
export class HTTPError extends BudibaseError {
|
||||||
|
status: number
|
||||||
|
|
||||||
|
constructor(message: string, httpStatus: number, code = ErrorCode.HTTP) {
|
||||||
|
super(message, code)
|
||||||
|
this.status = httpStatus
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LICENSING
|
||||||
|
|
||||||
|
export class UsageLimitError extends HTTPError {
|
||||||
|
limitName: string
|
||||||
|
|
||||||
|
constructor(message: string, limitName: string) {
|
||||||
|
super(message, 400, ErrorCode.USAGE_LIMIT_EXCEEDED)
|
||||||
|
this.limitName = limitName
|
||||||
|
}
|
||||||
|
|
||||||
|
getPublicError() {
|
||||||
|
return {
|
||||||
|
limitName: this.limitName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FeatureDisabledError extends HTTPError {
|
||||||
|
featureName: string
|
||||||
|
|
||||||
|
constructor(message: string, featureName: string) {
|
||||||
|
super(message, 400, ErrorCode.FEATURE_DISABLED)
|
||||||
|
this.featureName = featureName
|
||||||
|
}
|
||||||
|
|
||||||
|
getPublicError() {
|
||||||
|
return {
|
||||||
|
featureName: this.featureName,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { BudibaseError } from "./base"
|
|
||||||
|
|
||||||
export class GenericError extends BudibaseError {
|
|
||||||
constructor(message: string, code: string, type: string) {
|
|
||||||
super(message, code, type ? type : "generic")
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
import { GenericError } from "./generic"
|
|
||||||
|
|
||||||
export class HTTPError extends GenericError {
|
|
||||||
status: number
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
message: string,
|
|
||||||
httpStatus: number,
|
|
||||||
code = "http",
|
|
||||||
type = "generic"
|
|
||||||
) {
|
|
||||||
super(message, code, type)
|
|
||||||
this.status = httpStatus
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,3 +1 @@
|
||||||
export * from "./errors"
|
export * from "./errors"
|
||||||
export { UsageLimitError, FeatureDisabledError } from "./licensing"
|
|
||||||
export { HTTPError } from "./http"
|
|
||||||
|
|
|
@ -1,39 +0,0 @@
|
||||||
import { HTTPError } from "./http"
|
|
||||||
|
|
||||||
export const type = "license_error"
|
|
||||||
|
|
||||||
export const codes = {
|
|
||||||
USAGE_LIMIT_EXCEEDED: "usage_limit_exceeded",
|
|
||||||
FEATURE_DISABLED: "feature_disabled",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const context = {
|
|
||||||
[codes.USAGE_LIMIT_EXCEEDED]: (err: any) => {
|
|
||||||
return {
|
|
||||||
limitName: err.limitName,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[codes.FEATURE_DISABLED]: (err: any) => {
|
|
||||||
return {
|
|
||||||
featureName: err.featureName,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
export class UsageLimitError extends HTTPError {
|
|
||||||
limitName: string
|
|
||||||
|
|
||||||
constructor(message: string, limitName: string) {
|
|
||||||
super(message, 400, codes.USAGE_LIMIT_EXCEEDED, type)
|
|
||||||
this.limitName = limitName
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class FeatureDisabledError extends HTTPError {
|
|
||||||
featureName: string
|
|
||||||
|
|
||||||
constructor(message: string, featureName: string) {
|
|
||||||
super(message, 400, codes.FEATURE_DISABLED, type)
|
|
||||||
this.featureName = featureName
|
|
||||||
}
|
|
||||||
}
|
|
File diff suppressed because it is too large
Load Diff
|
@ -20,10 +20,10 @@ import {
|
||||||
cache,
|
cache,
|
||||||
tenancy,
|
tenancy,
|
||||||
context,
|
context,
|
||||||
errors,
|
|
||||||
events,
|
events,
|
||||||
migrations,
|
migrations,
|
||||||
objectStore,
|
objectStore,
|
||||||
|
ErrorCode,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import { USERS_TABLE_SCHEMA } from "../../constants"
|
import { USERS_TABLE_SCHEMA } from "../../constants"
|
||||||
import { buildDefaultDocs } from "../../db/defaultData/datasource_bb_default"
|
import { buildDefaultDocs } from "../../db/defaultData/datasource_bb_default"
|
||||||
|
@ -378,7 +378,7 @@ async function appPostCreate(ctx: BBContext, app: App) {
|
||||||
return quotas.addRows(rowCount)
|
return quotas.addRows(rowCount)
|
||||||
})
|
})
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code && err.code === errors.codes.USAGE_LIMIT_EXCEEDED) {
|
if (err.code && err.code === ErrorCode.USAGE_LIMIT_EXCEEDED) {
|
||||||
// this import resulted in row usage exceeding the quota
|
// this import resulted in row usage exceeding the quota
|
||||||
// delete the app
|
// delete the app
|
||||||
// skip pre and post-steps as no rows have been added to quotas yet
|
// skip pre and post-steps as no rows have been added to quotas yet
|
||||||
|
|
|
@ -2,11 +2,6 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@budibase/types@2.4.5-alpha.0":
|
|
||||||
version "2.4.5-alpha.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/@budibase/types/-/types-2.4.5-alpha.0.tgz#70fea09b5e471fe8fa6a760a1a2dd0dd74caac3a"
|
|
||||||
integrity sha512-tVFM9XnKwcCOo7nw6v7C8ZsK9hQLQBv3kHDn7/MFWnDMFCj72pUdtP/iFrAKr2c3tE84lkkWJfNHIolMSktHZA==
|
|
||||||
|
|
||||||
ansi-regex@^5.0.1:
|
ansi-regex@^5.0.1:
|
||||||
version "5.0.1"
|
version "5.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304"
|
||||||
|
|
|
@ -3,7 +3,6 @@ import {
|
||||||
getInviteCodes,
|
getInviteCodes,
|
||||||
updateInviteCode,
|
updateInviteCode,
|
||||||
} from "../../../utilities/redis"
|
} from "../../../utilities/redis"
|
||||||
// import sdk from "../../../sdk"
|
|
||||||
import * as userSdk from "../../../sdk/users"
|
import * as userSdk from "../../../sdk/users"
|
||||||
import env from "../../../environment"
|
import env from "../../../environment"
|
||||||
import {
|
import {
|
||||||
|
@ -26,11 +25,11 @@ import {
|
||||||
import {
|
import {
|
||||||
accounts,
|
accounts,
|
||||||
cache,
|
cache,
|
||||||
errors,
|
|
||||||
events,
|
events,
|
||||||
migrations,
|
migrations,
|
||||||
tenancy,
|
tenancy,
|
||||||
platform,
|
platform,
|
||||||
|
ErrorCode,
|
||||||
} from "@budibase/backend-core"
|
} from "@budibase/backend-core"
|
||||||
import { checkAnyUserExists } from "../../../utilities/users"
|
import { checkAnyUserExists } from "../../../utilities/users"
|
||||||
import { isEmailConfigured } from "../../../utilities/email"
|
import { isEmailConfigured } from "../../../utilities/email"
|
||||||
|
@ -421,7 +420,7 @@ export const inviteAccept = async (
|
||||||
email: user.email,
|
email: user.email,
|
||||||
}
|
}
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.code === errors.codes.USAGE_LIMIT_EXCEEDED) {
|
if (err.code === ErrorCode.USAGE_LIMIT_EXCEEDED) {
|
||||||
// explicitly re-throw limit exceeded errors
|
// explicitly re-throw limit exceeded errors
|
||||||
ctx.throw(400, err)
|
ctx.throw(400, err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue